Remove always defined FEATURE_CORECLR
[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 "security.h"
24 #include "cgensys.h"
25 #include "excep.h"
26 #include "dbginterface.h"
27 #include "dllimport.h"
28 #include "eeprofinterfaces.h"
29 #include "perfcounters.h"
30 #include "encee.h"
31 #include "jitinterface.h"
32 #include "eeconfig.h"
33 #include "dllimportcallback.h"
34 #include "contractimpl.h"
35 #include "typehash.h"
36 #include "instmethhash.h"
37 #include "virtualcallstub.h"
38 #include "typestring.h"
39 #include "stringliteralmap.h"
40 #include <formattype.h>
41 #include "fieldmarshaler.h"
42 #include "sigbuilder.h"
43 #include "tls.h"
44 #include "metadataexports.h"
45 #include "inlinetracking.h"
46
47 #ifdef FEATURE_REMOTING
48 #include "remoting.h"
49 #include "crossdomaincalls.h"
50 #include "objectclone.h"
51 #endif
52
53 #ifdef FEATURE_PREJIT
54 #include "exceptionhandling.h"
55 #include "corcompile.h"
56 #include "compile.h"
57 #include "nibblestream.h"
58 #include "zapsig.h"
59 #endif //FEATURE_PREJIT
60
61 #ifdef FEATURE_COMINTEROP 
62 #include "runtimecallablewrapper.h"
63 #include "comcallablewrapper.h"
64 #endif //FEATURE_COMINTEROP 
65
66 #ifdef _MSC_VER
67 #pragma warning(push)
68 #pragma warning(disable:4724)
69 #endif // _MSC_VER
70
71 #include "ngenhash.inl"
72
73 #ifdef _MSC_VER
74 #pragma warning(pop)
75 #endif // _MSC_VER
76
77
78 #include "perflog.h"
79 #include "ecall.h"
80 #include "../md/compiler/custattr.h"
81 #include "constrainedexecutionregion.h"
82 #include "typekey.h"
83 #include "peimagelayout.inl"
84 #include "ildbsymlib.h"
85
86 #if defined(FEATURE_APPX_BINDER)
87 #include "clrprivbinderappx.h"
88 #endif // defined(FEATURE_APPX_BINDER)
89
90 #if defined(PROFILING_SUPPORTED)
91 #include "profilermetadataemitvalidator.h"
92 #endif
93
94 #ifdef _MSC_VER
95 #pragma warning(push)
96 #pragma warning(disable:4244)
97 #endif // _MSC_VER
98
99 #ifdef _WIN64 
100 #define COR_VTABLE_PTRSIZED     COR_VTABLE_64BIT
101 #define COR_VTABLE_NOT_PTRSIZED COR_VTABLE_32BIT
102 #else // !_WIN64
103 #define COR_VTABLE_PTRSIZED     COR_VTABLE_32BIT
104 #define COR_VTABLE_NOT_PTRSIZED COR_VTABLE_64BIT
105 #endif // !_WIN64
106
107 #define CEE_FILE_GEN_GROWTH_COLLECTIBLE 2048
108
109 #define NGEN_STATICS_ALLCLASSES_WERE_LOADED -1
110
111
112 //---------------------------------------------------------------------------------------
113 InstrumentedILOffsetMapping::InstrumentedILOffsetMapping()
114 {
115     LIMITED_METHOD_DAC_CONTRACT;
116
117     m_cMap  = 0;
118     m_rgMap = NULL;
119     _ASSERTE(IsNull());
120 }
121
122 //---------------------------------------------------------------------------------------
123 //
124 // Check whether there is any mapping information stored in this object.
125 //
126 // Notes:
127 //    The memory should be alive throughout the process lifetime until 
128 //    the Module containing the instrumented method is destructed.
129 //
130
131 BOOL InstrumentedILOffsetMapping::IsNull()
132 {
133     LIMITED_METHOD_DAC_CONTRACT;
134
135     _ASSERTE((m_cMap == 0) == (m_rgMap == NULL));
136     return (m_cMap == 0);
137 }
138
139 #if !defined(DACCESS_COMPILE)
140 //---------------------------------------------------------------------------------------
141 //
142 // Release the memory used by the array of COR_IL_MAPs.
143 //
144 // Notes:
145 //    * The memory should be alive throughout the process lifetime until the Module containing 
146 //      the instrumented method is destructed.
147 //    * This struct should be read-only in DAC builds.
148 //
149
150 void InstrumentedILOffsetMapping::Clear()
151 {
152     LIMITED_METHOD_CONTRACT;
153
154     if (m_rgMap != NULL)
155     {
156         delete [] m_rgMap;
157     }
158
159     m_cMap  = 0;
160     m_rgMap = NULL;
161 }
162 #endif // !DACCESS_COMPILE
163
164 #if !defined(DACCESS_COMPILE)
165 void InstrumentedILOffsetMapping::SetMappingInfo(SIZE_T cMap, COR_IL_MAP * rgMap)
166 {
167     WRAPPER_NO_CONTRACT;
168     _ASSERTE((cMap == 0) == (rgMap == NULL));
169     m_cMap = cMap;
170     m_rgMap = ARRAY_PTR_COR_IL_MAP(rgMap);
171 }
172 #endif // !DACCESS_COMPILE
173
174 SIZE_T InstrumentedILOffsetMapping::GetCount() const
175 {
176     LIMITED_METHOD_DAC_CONTRACT;
177
178     _ASSERTE((m_cMap == 0) == (m_rgMap == NULL));
179     return m_cMap;
180 }
181
182 ARRAY_PTR_COR_IL_MAP InstrumentedILOffsetMapping::GetOffsets() const
183 {
184     LIMITED_METHOD_DAC_CONTRACT;
185
186     _ASSERTE((m_cMap == 0) == (m_rgMap == NULL));
187     return m_rgMap;
188 }
189
190 PTR_PersistentInlineTrackingMap Module::GetNgenInlineTrackingMap()
191 {
192     LIMITED_METHOD_DAC_CONTRACT;
193     return m_persistentInlineTrackingMap;
194 }
195
196
197 #ifndef DACCESS_COMPILE 
198
199 #ifdef FEATURE_MIXEDMODE
200
201 #include <pshpack1.h>
202 struct MUThunk
203 {
204     VASigCookie     *m_pCookie;
205     PCCOR_SIGNATURE  m_pSig;
206     LPVOID           m_pTarget;
207 #ifdef _TARGET_X86_ 
208     LPVOID           GetCode()
209     {
210         LIMITED_METHOD_CONTRACT;
211         return &m_op1;
212     }
213
214     BYTE             m_op1;     //0x58  POP   eax       ;;pop return address
215
216     BYTE             m_op2;     //0x68  PUSH  cookie
217     UINT32           m_opcookie;//
218
219     BYTE             m_op3;     //0x50  PUSH  eax       ;;repush return address
220
221     BYTE             m_op4;     //0xb8  MOV   eax,target
222     UINT32           m_optarget;//
223     BYTE             m_jmp;     //0xe9  JMP   PInvokeCalliStub
224     UINT32           m_jmptarg;
225 #else // !_TARGET_X86_
226     LPVOID           GetCode()
227     {
228         LIMITED_METHOD_CONTRACT;
229         PORTABILITY_ASSERT("MUThunk not implemented on this platform");
230         return NULL;
231     }
232 #endif // !_TARGET_X86_
233 };
234 #include <poppack.h>
235
236
237 //
238 // A hashtable for u->m thunks not represented in the fixup tables.
239 //
240 class MUThunkHash : public CClosedHashBase {
241     private:
242         //----------------------------------------------------
243         // Hash key for CClosedHashBase
244         //----------------------------------------------------
245         struct UTHKey {
246             LPVOID          m_pTarget;
247             PCCOR_SIGNATURE m_pSig;
248             DWORD           m_cSig;
249         };
250
251         //----------------------------------------------------
252         // Hash entry for CClosedHashBase
253         //----------------------------------------------------
254         struct UTHEntry {
255             UTHKey           m_key;
256             ELEMENTSTATUS    m_status;
257             MUThunk          *m_pMUThunk;
258         };
259
260     public:
261         MUThunkHash(Module *pModule) :
262             CClosedHashBase(
263 #ifdef _DEBUG 
264                              3,
265 #else // !_DEBUG
266                             17,    // CClosedHashTable will grow as necessary
267 #endif // !_DEBUG
268
269                             sizeof(UTHEntry),
270                             FALSE
271                             ),
272             m_crst(CrstMUThunkHash)
273
274         {
275             WRAPPER_NO_CONTRACT;
276             m_pModule = pModule;
277         }
278
279         ~MUThunkHash()
280         {
281             CONTRACT_VOID
282             {
283                 NOTHROW;
284                 DESTRUCTOR_CHECK;
285                 GC_NOTRIGGER;
286                 FORBID_FAULT;
287                 MODE_ANY;
288             }
289             CONTRACT_END
290
291             UTHEntry *phe = (UTHEntry*)GetFirst();
292             while (phe) {
293                 delete (BYTE*)phe->m_pMUThunk->m_pSig;
294                 DeleteExecutable(phe->m_pMUThunk);
295                 phe = (UTHEntry*)GetNext((BYTE*)phe);
296             }
297
298             RETURN;
299         }
300
301
302 #ifdef FEATURE_MIXEDMODE
303     public:
304         LPVOID GetMUThunk(LPVOID pTarget, PCCOR_SIGNATURE pSig0, DWORD cSig)
305         {
306             STATIC_CONTRACT_THROWS;
307
308             // A persistent copy of the sig
309             NewArrayHolder<COR_SIGNATURE> sigHolder = new COR_SIGNATURE[cSig];
310
311             memcpyNoGCRefs(sigHolder.GetValue(), pSig0, cSig);
312             sigHolder[0] = IMAGE_CEE_CS_CALLCONV_STDCALL;
313
314             // Have to lookup cookie eagerly because once we've added a blank
315             // entry to the hashtable, it's not easy to tolerate failure.
316             VASigCookie *pCookie = m_pModule->GetVASigCookie(Signature(sigHolder, cSig));
317
318             if (pCookie == NULL)
319             {
320                 return NULL;
321             }
322             sigHolder.SuppressRelease();
323             return GetMUThunkHelper(pTarget, sigHolder, cSig, pCookie);
324         }
325 private:
326         LPVOID GetMUThunkHelper(LPVOID pTarget, PCCOR_SIGNATURE pSig, DWORD cSig, VASigCookie *pCookie)
327         {
328             CONTRACT (LPVOID)
329             {
330                 INSTANCE_CHECK;
331                 THROWS;
332                 GC_TRIGGERS;
333                 MODE_ANY;
334                 INJECT_FAULT(COMPlusThrowOM());
335                 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
336             }
337             CONTRACT_END
338
339             UTHEntry *phe;
340             CrstHolder ch(&m_crst);
341
342             UTHKey key;
343             key.m_pTarget = pTarget;
344             key.m_pSig    = pSig;
345             key.m_cSig    = cSig;
346
347             bool bNew;
348             phe = (UTHEntry*)FindOrAdd((LPVOID)&key, /*modifies*/bNew);
349
350             if (phe)
351             {
352                 if (bNew)
353                 {
354                     phe->m_pMUThunk = new (executable) MUThunk;
355                     phe->m_pMUThunk->m_pCookie = pCookie;
356                     phe->m_pMUThunk->m_pSig    = pSig;
357                     phe->m_pMUThunk->m_pTarget = pTarget;
358 #ifdef _TARGET_X86_ 
359                     phe->m_pMUThunk->m_op1      = 0x58;       //POP EAX
360                     phe->m_pMUThunk->m_op2      = 0x68;       //PUSH
361                     phe->m_pMUThunk->m_opcookie = (UINT32)(size_t)pCookie;
362                     phe->m_pMUThunk->m_op3      = 0x50;       //POP EAX
363                     phe->m_pMUThunk->m_op4      = 0xb8;       //mov eax
364                     phe->m_pMUThunk->m_optarget = (UINT32)(size_t)pTarget;
365                     phe->m_pMUThunk->m_jmp      = 0xe9;       //jmp
366                     phe->m_pMUThunk->m_jmptarg  = (UINT32)(GetEEFuncEntryPoint(GenericPInvokeCalliHelper) - ((size_t)( 1 + &(phe->m_pMUThunk->m_jmptarg))));
367 #else // !_TARGET_X86_
368                     PORTABILITY_ASSERT("MUThunkHash not implemented on this platform");
369 #endif // !_TARGET_X86_
370
371                     phe->m_key = key;
372                     phe->m_status = USED;
373                 }
374                 else
375                 {
376                     delete[] (BYTE*)pSig;
377                 }
378             }
379             else
380             {
381                 delete[] (BYTE*)pSig;
382             }
383
384             if (phe)
385                 RETURN (LPVOID)(phe->m_pMUThunk->GetCode());
386             else
387                 RETURN NULL;
388         }
389 #endif // FEATURE_MIXEDMODE
390
391 public:
392
393         // *** OVERRIDES FOR CClosedHashBase ***/
394
395         //*****************************************************************************
396         // Hash is called with a pointer to an element in the table.  You must override
397         // this method and provide a hash algorithm for your element type.
398         //*****************************************************************************
399             virtual unsigned int Hash(             // The key value.
400                 void const  *pData)                 // Raw data to hash.
401             {
402                 LIMITED_METHOD_CONTRACT;
403
404                 UTHKey *pKey = (UTHKey*)pData;
405                 return (ULONG)(size_t)(pKey->m_pTarget);
406             }
407
408
409         //*****************************************************************************
410         // Compare is used in the typical memcmp way, 0 is eqaulity, -1/1 indicate
411         // direction of miscompare.  In this system everything is always equal or not.
412         //*****************************************************************************
413         unsigned int Compare(          // 0, -1, or 1.
414                               void const  *pData,               // Raw key data on lookup.
415                               BYTE        *pElement)            // The element to compare data against.
416         {
417             CONTRACTL
418             {
419                 NOTHROW;
420                 GC_TRIGGERS;
421                 MODE_ANY;
422             }
423             CONTRACTL_END;
424
425             UTHKey *pkey1 = (UTHKey*)pData;
426             UTHKey *pkey2 = &( ((UTHEntry*)pElement)->m_key );
427
428             if (pkey1->m_pTarget != pkey2->m_pTarget)
429                 return 1;
430
431             if (S_OK != MetaSig::CompareMethodSigsNT(pkey1->m_pSig, pkey1->m_cSig, m_pModule, NULL, pkey2->m_pSig, pkey2->m_cSig, m_pModule, NULL))
432                 return 1;
433
434             return 0;
435         }
436
437         //*****************************************************************************
438         // Return true if the element is free to be used.
439         //*****************************************************************************
440             virtual ELEMENTSTATUS Status(           // The status of the entry.
441                 BYTE        *pElement)            // The element to check.
442             {
443                 LIMITED_METHOD_CONTRACT;
444
445                 return ((UTHEntry*)pElement)->m_status;
446             }
447
448         //*****************************************************************************
449         // Sets the status of the given element.
450         //*****************************************************************************
451             virtual void SetStatus(
452                 BYTE        *pElement,              // The element to set status for.
453                 ELEMENTSTATUS eStatus)            // New status.
454             {
455                 LIMITED_METHOD_CONTRACT;
456
457                 ((UTHEntry*)pElement)->m_status = eStatus;
458             }
459
460         //*****************************************************************************
461         // Returns the internal key value for an element.
462         //*****************************************************************************
463             virtual void *GetKey(                   // The data to hash on.
464                 BYTE        *pElement)            // The element to return data ptr for.
465             {
466                 LIMITED_METHOD_CONTRACT;
467                 return (BYTE*) &(((UTHEntry*)pElement)->m_key);
468             }
469
470
471
472         Module      *m_pModule;
473         Crst         m_crst;
474 };
475 #endif // FEATURE_MIXEDMODE
476
477
478 // ===========================================================================
479 // Module
480 // ===========================================================================
481
482 //---------------------------------------------------------------------------------------------------
483 // This wrapper just invokes the real initialization inside a try/hook.
484 // szName is not null only for dynamic modules
485 //---------------------------------------------------------------------------------------------------
486 void Module::DoInit(AllocMemTracker *pamTracker, LPCWSTR szName)
487 {
488     CONTRACTL
489     {
490         INSTANCE_CHECK;
491         STANDARD_VM_CHECK;
492     }
493     CONTRACTL_END;
494
495 #ifdef PROFILING_SUPPORTED
496     {
497         BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
498         GCX_COOP();
499         g_profControlBlock.pProfInterface->ModuleLoadStarted((ModuleID) this);
500         END_PIN_PROFILER();
501     }
502     // Need TRY/HOOK instead of holder so we can get HR of exception thrown for profiler callback
503     EX_TRY
504 #endif
505     {
506         Initialize(pamTracker, szName);
507     }
508 #ifdef PROFILING_SUPPORTED
509     
510
511     EX_HOOK
512     {
513         {
514             BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
515             g_profControlBlock.pProfInterface->ModuleLoadFinished((ModuleID) this, GET_EXCEPTION()->GetHR());
516             END_PIN_PROFILER();
517         }
518     }
519     EX_END_HOOK;
520
521 #endif
522 }
523
524 // Set the given bit on m_dwTransientFlags. Return true if we won the race to set the bit.
525 BOOL Module::SetTransientFlagInterlocked(DWORD dwFlag)
526 {
527     LIMITED_METHOD_CONTRACT;
528
529     for (;;)
530     {
531         DWORD dwTransientFlags = m_dwTransientFlags;
532         if ((dwTransientFlags & dwFlag) != 0)
533             return FALSE;
534         if ((DWORD)FastInterlockCompareExchange((LONG*)&m_dwTransientFlags, dwTransientFlags | dwFlag, dwTransientFlags) == dwTransientFlags)
535             return TRUE;
536     }
537 }
538
539 #if PROFILING_SUPPORTED 
540 void Module::NotifyProfilerLoadFinished(HRESULT hr)
541 {
542     CONTRACTL
543     {
544         INSTANCE_CHECK;
545         THROWS;
546         GC_TRIGGERS;
547         INJECT_FAULT(COMPlusThrowOM());
548         MODE_ANY;
549     }
550     CONTRACTL_END;
551
552     // Note that in general we wil reuse shared modules.  So we need to make sure we only notify
553     // the profiler once.
554     if (SetTransientFlagInterlocked(IS_PROFILER_NOTIFIED))
555     {
556         // Record how many types are already present
557         DWORD countTypesOrig = 0;
558         DWORD countExportedTypesOrig = 0;
559         if (!IsResource())
560         {
561             countTypesOrig = GetMDImport()->GetCountWithTokenKind(mdtTypeDef);
562             countExportedTypesOrig = GetMDImport()->GetCountWithTokenKind(mdtExportedType);
563         }
564
565         // Notify the profiler, this may cause metadata to be updated
566         {
567             BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
568             {
569                 GCX_PREEMP();
570                 g_profControlBlock.pProfInterface->ModuleLoadFinished((ModuleID) this, hr);
571
572                 if (SUCCEEDED(hr))
573                 {
574                     g_profControlBlock.pProfInterface->ModuleAttachedToAssembly((ModuleID) this,
575                                                                                 (AssemblyID)m_pAssembly);
576                 }
577             }
578             END_PIN_PROFILER();
579         }
580
581         // If there are more types than before, add these new types to the
582         // assembly
583         if (!IsResource())
584         {
585             DWORD countTypesAfterProfilerUpdate = GetMDImport()->GetCountWithTokenKind(mdtTypeDef);
586             DWORD countExportedTypesAfterProfilerUpdate = GetMDImport()->GetCountWithTokenKind(mdtExportedType);
587             // 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
588             for (DWORD typeDefRid = countTypesOrig + 2; typeDefRid < countTypesAfterProfilerUpdate + 2; typeDefRid++)
589             {
590                 GetAssembly()->AddType(this, TokenFromRid(typeDefRid, mdtTypeDef));
591             }
592             // 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
593             for (DWORD exportedTypeDef = countExportedTypesOrig + 1; exportedTypeDef < countExportedTypesAfterProfilerUpdate + 1; exportedTypeDef++)
594             {
595                 GetAssembly()->AddExportedType(TokenFromRid(exportedTypeDef, mdtExportedType));
596             }
597         }
598
599         {
600             BEGIN_PIN_PROFILER(CORProfilerTrackAssemblyLoads());
601             if (IsManifest())
602             {
603                 GCX_COOP();
604                 g_profControlBlock.pProfInterface->AssemblyLoadFinished((AssemblyID) m_pAssembly, hr);
605             }
606             END_PIN_PROFILER();
607         }
608     }
609 }
610
611 #ifndef CROSSGEN_COMPILE
612 IMetaDataEmit *Module::GetValidatedEmitter()
613 {
614     CONTRACTL
615     {
616         INSTANCE_CHECK;
617         THROWS;
618         GC_NOTRIGGER;
619         INJECT_FAULT(COMPlusThrowOM());
620         MODE_ANY;
621     }
622     CONTRACTL_END;
623
624     if (m_pValidatedEmitter.Load() == NULL)
625     {
626         // In the past profilers could call any API they wanted on the the IMetaDataEmit interface and we didn't
627         // verify anything. To ensure we don't break back-compat the verifications are not enabled by default.
628         // Right now I have only added verifications for NGEN images, but in the future we might want verifications
629         // for all modules.
630         IMetaDataEmit* pEmit = NULL;
631         if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation) && HasNativeImage())
632         {
633             ProfilerMetadataEmitValidator* pValidator = new ProfilerMetadataEmitValidator(GetEmitter());
634             pValidator->QueryInterface(IID_IMetaDataEmit, (void**)&pEmit);
635         }
636         else
637         {
638             pEmit = GetEmitter();
639             pEmit->AddRef();
640         }
641         // Atomically swap it into the field (release it if we lose the race)
642         if (FastInterlockCompareExchangePointer(&m_pValidatedEmitter, pEmit, NULL) != NULL)
643         {
644             pEmit->Release();
645         }
646     }
647     return m_pValidatedEmitter.Load();
648 }
649 #endif // CROSSGEN_COMPILE
650 #endif // PROFILING_SUPPORTED
651
652 void Module::NotifyEtwLoadFinished(HRESULT hr)
653 {
654     CONTRACTL
655     {
656         NOTHROW;
657         GC_TRIGGERS;
658     }
659     CONTRACTL_END
660
661     // we report only successful loads
662     if (SUCCEEDED(hr) &&
663         ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, 
664                                      TRACE_LEVEL_INFORMATION, 
665                                      KEYWORDZERO))
666     {
667         BOOL fSharedModule = !SetTransientFlagInterlocked(IS_ETW_NOTIFIED);
668         ETW::LoaderLog::ModuleLoad(this, fSharedModule);
669     }
670 }
671
672 // Module initialization occurs in two phases: the constructor phase and the Initialize phase.
673 //
674 // The constructor phase initializes just enough so that Destruct() can be safely called.
675 // It cannot throw or fail.
676 //
677 Module::Module(Assembly *pAssembly, mdFile moduleRef, PEFile *file)
678 {
679     CONTRACTL
680     {
681         NOTHROW;
682         GC_TRIGGERS;
683         FORBID_FAULT;
684     }
685     CONTRACTL_END
686
687     PREFIX_ASSUME(pAssembly != NULL);
688
689     m_pAssembly = pAssembly;
690     m_moduleRef = moduleRef;
691     m_file      = file;
692     m_dwTransientFlags = CLASSES_FREED;
693
694     if (!m_file->HasNativeImage())
695     {
696         // Memory allocated on LoaderHeap is zero-filled. Spot-check it here.
697         _ASSERTE(m_pBinder == NULL);
698         _ASSERTE(m_symbolFormat == eSymbolFormatNone);
699     }
700     
701     file->AddRef();
702 }
703
704
705 #ifdef FEATURE_PREJIT 
706
707 void Module::InitializeNativeImage(AllocMemTracker* pamTracker)
708 {
709     CONTRACTL
710     {
711         INSTANCE_CHECK;
712         THROWS;
713         GC_TRIGGERS;
714         MODE_PREEMPTIVE;
715         PRECONDITION(HasNativeImage());
716     }
717     CONTRACTL_END;
718
719     if(m_pModuleSecurityDescriptor)
720     {
721         _ASSERTE(m_pModuleSecurityDescriptor->GetModule() == this);
722     }
723
724     PEImageLayout * pNativeImage = GetNativeImage();
725
726     ExecutionManager::AddNativeImageRange(dac_cast<TADDR>(pNativeImage->GetBase()), pNativeImage->GetVirtualSize(), this);
727
728     CORCOMPILE_VERSION_INFO * pNativeVersionInfo = pNativeImage->GetNativeVersionInfoMaybeNull();
729     if ((pNativeVersionInfo != NULL) && (pNativeVersionInfo->wConfigFlags & CORCOMPILE_CONFIG_INSTRUMENTATION))
730     {
731         m_nativeImageProfiling = GetAssembly()->IsInstrumented();
732     }
733
734     // Link the module to the profile data list if available.
735     COUNT_T cbProfileList;
736     m_methodProfileList = pNativeImage->GetNativeProfileDataList(&cbProfileList);
737 #ifdef FEATURE_LAZY_COW_PAGES
738     if (cbProfileList)
739         EnsureWritablePages(m_methodProfileList, cbProfileList);
740 #endif
741
742 #ifndef CROSSGEN_COMPILE
743     LoadTokenTables();
744     LoadHelperTable();
745 #endif // CROSSGEN_COMPILE
746
747 #if defined(HAVE_GCCOVER)
748     if (GCStress<cfg_instr_ngen>::IsEnabled())
749     {
750         // Setting up gc coverage requires the base system classes
751         //  to be initialized. So we must defer this for mscorlib.
752         if(!IsSystem())
753         {
754             SetupGcCoverageForNativeImage(this);
755         }
756     }
757 #endif // defined(HAVE_GCCOVER)
758 }
759
760 void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssembly)
761 {
762     CONTRACTL
763     {
764         THROWS;
765         GC_TRIGGERS;
766         MODE_ANY;
767     }
768     CONTRACTL_END;
769
770     if (m_NativeMetadataAssemblyRefMap == NULL)
771     {
772         IMDInternalImport* pImport = GetNativeAssemblyImport();
773         DWORD dwMaxRid = pImport->GetCountWithTokenKind(mdtAssemblyRef);
774         _ASSERTE(dwMaxRid > 0);
775
776         S_SIZE_T dwAllocSize = S_SIZE_T(sizeof(PTR_Assembly)) * S_SIZE_T(dwMaxRid);
777
778         AllocMemTracker amTracker;
779         PTR_Assembly * NativeMetadataAssemblyRefMap = (PTR_Assembly *) amTracker.Track( GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(dwAllocSize) );
780
781         // Note: Memory allocated on loader heap is zero filled
782
783         if (InterlockedCompareExchangeT<PTR_Assembly *>(&m_NativeMetadataAssemblyRefMap, NativeMetadataAssemblyRefMap, NULL) == NULL)
784             amTracker.SuppressRelease();
785     }
786     _ASSERTE(m_NativeMetadataAssemblyRefMap != NULL);
787
788     _ASSERTE(rid <= GetNativeAssemblyImport()->GetCountWithTokenKind(mdtAssemblyRef));
789     m_NativeMetadataAssemblyRefMap[rid-1] = pAssembly;
790
791 #else // FEATURE_PREJIT 
792 BOOL Module::IsPersistedObject(void *address)
793 {
794     LIMITED_METHOD_CONTRACT;
795     return FALSE;
796 }
797
798 #endif // FEATURE_PREJIT 
799
800 // Module initialization occurs in two phases: the constructor phase and the Initialize phase.
801 //
802 // The Initialize() phase completes the initialization after the constructor has run.
803 // It can throw exceptions but whether it throws or succeeds, it must leave the Module
804 // in a state where Destruct() can be safely called.
805 // 
806 // szName is only used by dynamic modules, see ReflectionModule::Initialize
807 // 
808 //
809 void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName)
810 {
811     CONTRACTL
812     {
813         INSTANCE_CHECK;
814         STANDARD_VM_CHECK;
815         PRECONDITION(szName == NULL);
816     }
817     CONTRACTL_END;
818
819     m_pSimpleName = m_file->GetSimpleName();
820
821     m_Crst.Init(CrstModule);
822     m_LookupTableCrst.Init(CrstModuleLookupTable, CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD));
823     m_FixupCrst.Init(CrstModuleFixup, (CrstFlags)(CRST_HOST_BREAKABLE|CRST_REENTRANCY));
824     m_InstMethodHashTableCrst.Init(CrstInstMethodHashTable, CRST_REENTRANCY);
825     m_ISymUnmanagedReaderCrst.Init(CrstISymUnmanagedReader, CRST_DEBUGGER_THREAD);
826
827     if (!m_file->HasNativeImage())
828     {
829         AllocateMaps();
830
831         if (IsSystem() ||
832             (strcmp(m_pSimpleName, "System") == 0) ||
833             (strcmp(m_pSimpleName, "System.Core") == 0) ||
834             (strcmp(m_pSimpleName, "Windows.Foundation") == 0))
835         {
836             FastInterlockOr(&m_dwPersistedFlags, LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME);
837         }
838
839         _ASSERT(m_pModuleSecurityDescriptor == NULL);
840         m_pModuleSecurityDescriptor = new ModuleSecurityDescriptor(this);
841     }
842
843     m_dwTransientFlags &= ~((DWORD)CLASSES_FREED);  // Set flag indicating LookupMaps are now in a consistent and destructable state
844
845 #ifdef FEATURE_READYTORUN
846     if (!HasNativeImage() && !IsResource())
847         m_pReadyToRunInfo = ReadyToRunInfo::Initialize(this, pamTracker);
848 #endif
849
850     // Initialize the instance fields that we need for all non-Resource Modules
851     if (!IsResource())
852     {
853         if (m_pAvailableClasses == NULL && !IsReadyToRun())
854         {
855             m_pAvailableClasses = EEClassHashTable::Create(this,
856                 GetAssembly()->IsCollectible() ? AVAILABLE_CLASSES_HASH_BUCKETS_COLLECTIBLE : AVAILABLE_CLASSES_HASH_BUCKETS,
857                                                            FALSE /* bCaseInsensitive */, pamTracker);
858         }
859
860         if (m_pAvailableParamTypes == NULL)
861         {
862             m_pAvailableParamTypes = EETypeHashTable::Create(GetLoaderAllocator(), this, PARAMTYPES_HASH_BUCKETS, pamTracker);
863         }
864
865         if (m_pInstMethodHashTable == NULL)
866         {
867             m_pInstMethodHashTable = InstMethodHashTable::Create(GetLoaderAllocator(), this, PARAMMETHODS_HASH_BUCKETS, pamTracker);
868         }
869
870         if(m_pMemberRefToDescHashTable == NULL)
871         {
872             if (IsReflection())
873             {
874                 m_pMemberRefToDescHashTable = MemberRefToDescHashTable::Create(this, MEMBERREF_MAP_INITIAL_SIZE, pamTracker);
875             }
876             else
877             {
878                                 IMDInternalImport * pImport = GetMDImport();
879
880                 // Get #MemberRefs and create memberrefToDesc hash table
881                 m_pMemberRefToDescHashTable = MemberRefToDescHashTable::Create(this, pImport->GetCountWithTokenKind(mdtMemberRef)+1, pamTracker);
882             }
883         }
884
885 #ifdef FEATURE_COMINTEROP
886         if (IsCompilationProcess() && m_pGuidToTypeHash == NULL)
887         {
888             // only allocate this during NGEN-ing
889             m_pGuidToTypeHash = GuidToMethodTableHashTable::Create(this, GUID_TO_TYPE_HASH_BUCKETS, pamTracker);
890         }
891 #endif // FEATURE_COMINTEROP
892     }
893
894     if (GetAssembly()->IsDomainNeutral() && !IsSingleAppDomain())
895     {
896         m_ModuleIndex = Module::AllocateModuleIndex();
897         m_ModuleID = (DomainLocalModule*)Module::IndexToID(m_ModuleIndex);
898     }
899     else
900     {
901         // this will be initialized a bit later.
902         m_ModuleID = NULL;
903         m_ModuleIndex.m_dwIndex = (SIZE_T)-1;
904     }
905
906 #ifdef FEATURE_COLLECTIBLE_TYPES
907     if (GetAssembly()->IsCollectible())
908     {
909         FastInterlockOr(&m_dwPersistedFlags, COLLECTIBLE_MODULE);
910     }
911 #endif // FEATURE_COLLECTIBLE_TYPES
912
913     // Prepare statics that are known at module load time
914     AllocateStatics(pamTracker);
915
916 #ifdef FEATURE_PREJIT 
917     // Set up native image
918     if (HasNativeImage())
919         InitializeNativeImage(pamTracker);
920 #endif // FEATURE_PREJIT
921
922
923 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
924     if (g_CorCompileVerboseLevel)
925         m_pNgenStats = new NgenStats();
926 #endif
927
928     if (!IsResource() && (m_AssemblyRefByNameTable == NULL))
929     {
930         Module::CreateAssemblyRefByNameTable(pamTracker);
931     }
932     
933     // If the program has the "ForceEnc" env variable set we ensure every eligible
934     // module has EnC turned on.
935     if (g_pConfig->ForceEnc() && IsEditAndContinueCapable())
936         EnableEditAndContinue();
937
938     LOG((LF_CLASSLOADER, LL_INFO10, "Loaded pModule: \"%ws\".\n", GetDebugName()));
939
940 }
941
942 #endif // DACCESS_COMPILE
943
944
945 #ifdef FEATURE_COMINTEROP
946
947 #ifndef DACCESS_COMPILE
948
949 // static
950 GuidToMethodTableHashTable* GuidToMethodTableHashTable::Create(Module* pModule, DWORD cInitialBuckets, 
951                         AllocMemTracker *pamTracker)
952 {
953     CONTRACTL
954     {
955         THROWS;
956         GC_TRIGGERS;
957         MODE_ANY;
958         INJECT_FAULT(COMPlusThrowOM(););
959         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
960     }
961     CONTRACTL_END;
962
963     LoaderHeap *pHeap = pModule->GetAssembly()->GetLowFrequencyHeap();
964     GuidToMethodTableHashTable *pThis = (GuidToMethodTableHashTable*)pamTracker->Track(pHeap->AllocMem((S_SIZE_T)sizeof(GuidToMethodTableHashTable)));
965
966     // The base class get initialized through chaining of constructors. We allocated the hash instance via the
967     // loader heap instead of new so use an in-place new to call the constructors now.
968     new (pThis) GuidToMethodTableHashTable(pModule, pHeap, cInitialBuckets);
969
970     return pThis;
971 }
972
973 GuidToMethodTableEntry *GuidToMethodTableHashTable::InsertValue(PTR_GUID pGuid, PTR_MethodTable pMT, 
974                         BOOL bReplaceIfFound, AllocMemTracker *pamTracker)
975 {
976     CONTRACTL
977     {
978         THROWS;
979         GC_NOTRIGGER;
980         MODE_ANY;
981         INJECT_FAULT(COMPlusThrowOM(););
982         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
983     }
984     CONTRACTL_END;
985
986     GuidToMethodTableEntry *pEntry = NULL;
987     LookupContext ctx;
988
989     if (bReplaceIfFound)
990     {
991         pEntry = FindItem(pGuid, NULL);
992     }
993
994     if (pEntry != NULL)
995     {
996         pEntry->m_pMT = pMT;
997     }
998     else
999     {
1000         pEntry = BaseAllocateEntry(pamTracker);
1001         pEntry->m_Guid = pGuid;
1002         pEntry->m_pMT = pMT;
1003
1004         DWORD hash = Hash(pGuid);
1005         BaseInsertEntry(hash, pEntry);
1006     }
1007
1008     return pEntry;
1009 }
1010
1011 #endif // !DACCESS_COMPILE
1012
1013 PTR_MethodTable GuidToMethodTableHashTable::GetValue(const GUID * pGuid, LookupContext *pContext)
1014 {
1015     CONTRACTL
1016     {
1017         NOTHROW;
1018         GC_NOTRIGGER;
1019         MODE_ANY;
1020         SUPPORTS_DAC;
1021         PRECONDITION(CheckPointer(pGuid));
1022     }
1023     CONTRACTL_END;
1024
1025     GuidToMethodTableEntry * pEntry = FindItem(pGuid, pContext);
1026     if (pEntry != NULL)
1027     {
1028         return pEntry->m_pMT;
1029     }
1030
1031     return NULL;
1032 }
1033
1034 GuidToMethodTableEntry *GuidToMethodTableHashTable::FindItem(const GUID * pGuid, LookupContext *pContext)
1035 {
1036     CONTRACTL
1037     {
1038         NOTHROW;
1039         GC_NOTRIGGER;
1040         MODE_ANY;
1041         SUPPORTS_DAC;
1042         PRECONDITION(CheckPointer(pGuid));
1043     }
1044     CONTRACTL_END;
1045
1046     // It's legal for the caller not to pass us a LookupContext, but we might need to iterate
1047     // internally (since we lookup via hash and hashes may collide). So substitute our own 
1048     // private context if one was not provided.
1049     LookupContext sAltContext;
1050     if (pContext == NULL)
1051         pContext = &sAltContext;
1052
1053     // The base class provides the ability to enumerate all entries with the same hash code. 
1054     // We further check which of these entries actually match the full key.
1055     PTR_GuidToMethodTableEntry pSearch = BaseFindFirstEntryByHash(Hash(pGuid), pContext);
1056     while (pSearch)
1057     {
1058         if (CompareKeys(pSearch, pGuid)) 
1059         {
1060             return pSearch;
1061         }
1062
1063         pSearch = BaseFindNextEntryByHash(pContext);
1064     }
1065
1066     return NULL;
1067 }
1068
1069 BOOL GuidToMethodTableHashTable::CompareKeys(PTR_GuidToMethodTableEntry pEntry, const GUID * pGuid)
1070 {
1071     LIMITED_METHOD_DAC_CONTRACT;
1072     return *pGuid == *(pEntry->m_Guid);
1073 }
1074
1075 DWORD GuidToMethodTableHashTable::Hash(const GUID * pGuid)
1076 {
1077     LIMITED_METHOD_DAC_CONTRACT;
1078     static_assert_no_msg(sizeof(GUID) % sizeof(DWORD) == 0);
1079     static_assert_no_msg(sizeof(GUID) / sizeof(DWORD) == 4);
1080     DWORD * pSlice = (DWORD*) pGuid;
1081     return pSlice[0] ^ pSlice[1] ^ pSlice[2] ^ pSlice[3];
1082 }
1083
1084
1085 BOOL GuidToMethodTableHashTable::FindNext(Iterator *it, GuidToMethodTableEntry **ppEntry)
1086 {
1087     LIMITED_METHOD_DAC_CONTRACT;
1088
1089     if (!it->m_fIterating)
1090     {
1091         BaseInitIterator(&it->m_sIterator);
1092         it->m_fIterating = true;
1093     }
1094
1095     *ppEntry = it->m_sIterator.Next();
1096     return *ppEntry ? TRUE : FALSE;
1097 }
1098
1099 DWORD GuidToMethodTableHashTable::GetCount()
1100 {
1101     LIMITED_METHOD_DAC_CONTRACT;
1102     return BaseGetElementCount();
1103 }
1104
1105 #if defined(FEATURE_NATIVE_IMAGE_GENERATION) && !defined(DACCESS_COMPILE)
1106
1107 void GuidToMethodTableHashTable::Save(DataImage *pImage, CorProfileData *pProfileData)
1108 {
1109     WRAPPER_NO_CONTRACT;
1110     Base_t::BaseSave(pImage, pProfileData);
1111 }
1112
1113 void GuidToMethodTableHashTable::Fixup(DataImage *pImage)
1114 {
1115     WRAPPER_NO_CONTRACT;
1116     Base_t::BaseFixup(pImage);
1117 }
1118
1119 bool GuidToMethodTableHashTable::SaveEntry(DataImage *pImage, CorProfileData *pProfileData, 
1120                     GuidToMethodTableEntry *pOldEntry, GuidToMethodTableEntry *pNewEntry, 
1121                     EntryMappingTable *pMap)
1122
1123     LIMITED_METHOD_CONTRACT;
1124     return false;
1125 }
1126
1127 void GuidToMethodTableHashTable::FixupEntry(DataImage *pImage, GuidToMethodTableEntry *pEntry, void *pFixupBase, DWORD cbFixupOffset)
1128 {
1129     WRAPPER_NO_CONTRACT;
1130     pImage->FixupField(pFixupBase, cbFixupOffset + offsetof(GuidToMethodTableEntry, m_pMT), pEntry->m_pMT);
1131     pImage->FixupField(pFixupBase, cbFixupOffset + offsetof(GuidToMethodTableEntry, m_Guid), pEntry->m_Guid);
1132 }
1133     
1134 #endif // FEATURE_NATIVE_IMAGE_GENERATION && !DACCESS_COMPILE
1135
1136
1137 #ifdef FEATURE_PREJIT
1138
1139 #ifndef DACCESS_COMPILE
1140 BOOL Module::CanCacheWinRTTypeByGuid(MethodTable *pMT)
1141 {
1142     CONTRACTL
1143     {
1144         THROWS;
1145         GC_NOTRIGGER;
1146         MODE_ANY;
1147         PRECONDITION(IsCompilationProcess());
1148     }
1149     CONTRACTL_END;
1150
1151     // Don't cache mscorlib-internal declarations of WinRT types.
1152     if (IsSystem() && pMT->IsProjectedFromWinRT())
1153         return FALSE;
1154
1155     // Don't cache redirected WinRT types.
1156     if (WinRTTypeNameConverter::IsRedirectedWinRTSourceType(pMT))
1157         return FALSE;
1158
1159 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
1160     // Don't cache in a module that's not the NGen target, since the result
1161     // won't be saved, and since the such a module might be read-only.
1162     if (GetAppDomain()->ToCompilationDomain()->GetTargetModule() != this)
1163         return FALSE;
1164 #endif
1165
1166     return TRUE;
1167 }
1168
1169 void Module::CacheWinRTTypeByGuid(PTR_MethodTable pMT, PTR_GuidInfo pgi /*= NULL*/)
1170 {
1171     CONTRACTL
1172     {
1173         STANDARD_VM_CHECK;
1174         PRECONDITION(CheckPointer(pMT));
1175         PRECONDITION(pMT->IsLegalNonArrayWinRTType());
1176         PRECONDITION(pgi != NULL || pMT->GetGuidInfo() != NULL);
1177         PRECONDITION(IsCompilationProcess());
1178     }
1179     CONTRACTL_END;
1180
1181     if (pgi == NULL)
1182     {
1183         pgi = pMT->GetGuidInfo();
1184     }
1185
1186     AllocMemTracker amt;
1187     m_pGuidToTypeHash->InsertValue(&pgi->m_Guid, pMT, TRUE, &amt);
1188     amt.SuppressRelease();
1189 }
1190
1191 #endif // !DACCESS_COMPILE
1192
1193 PTR_MethodTable Module::LookupTypeByGuid(const GUID & guid)
1194 {
1195     WRAPPER_NO_CONTRACT;
1196     // Triton ni images do not have this hash.
1197     if (m_pGuidToTypeHash != NULL)
1198         return m_pGuidToTypeHash->GetValue(&guid, NULL);
1199     else
1200         return NULL;
1201 }
1202
1203 void Module::GetCachedWinRTTypes(SArray<PTR_MethodTable> * pTypes, SArray<GUID> * pGuids)
1204 {
1205     CONTRACTL
1206     {
1207         STANDARD_VM_CHECK;
1208         SUPPORTS_DAC;
1209     }
1210     CONTRACTL_END;
1211
1212     // Triton ni images do not have this hash.
1213     if (m_pGuidToTypeHash != NULL)
1214     {
1215         GuidToMethodTableHashTable::Iterator it(m_pGuidToTypeHash);
1216         GuidToMethodTableEntry *pEntry;
1217         while (m_pGuidToTypeHash->FindNext(&it, &pEntry))
1218         {
1219             pTypes->Append(pEntry->m_pMT);
1220             pGuids->Append(*pEntry->m_Guid);
1221         }
1222     }
1223 }
1224
1225 #endif // FEATURE_PREJIT
1226
1227 #endif // FEATURE_COMINTEROP
1228
1229 #ifndef DACCESS_COMPILE
1230 MemberRefToDescHashTable* MemberRefToDescHashTable::Create(Module *pModule, DWORD cInitialBuckets, AllocMemTracker *pamTracker)
1231 {
1232     CONTRACTL
1233     {
1234         THROWS;
1235         GC_TRIGGERS;
1236         MODE_ANY;
1237         INJECT_FAULT(COMPlusThrowOM(););
1238         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
1239     }
1240     CONTRACTL_END;
1241
1242     LoaderHeap *pHeap = pModule->GetAssembly()->GetLowFrequencyHeap();
1243     MemberRefToDescHashTable *pThis = (MemberRefToDescHashTable*)pamTracker->Track(pHeap->AllocMem((S_SIZE_T)sizeof(MemberRefToDescHashTable)));
1244
1245     // The base class get initialized through chaining of constructors. We allocated the hash instance via the
1246     // loader heap instead of new so use an in-place new to call the constructors now.
1247     new (pThis) MemberRefToDescHashTable(pModule, pHeap, cInitialBuckets);
1248
1249     return pThis;
1250 }
1251
1252 //Inserts FieldRef 
1253 MemberRefToDescHashEntry* MemberRefToDescHashTable::Insert(mdMemberRef token , FieldDesc *value)
1254 {
1255     CONTRACTL
1256     {
1257         THROWS;
1258         GC_NOTRIGGER;
1259         MODE_ANY;
1260         INJECT_FAULT(COMPlusThrowOM(););
1261         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
1262     }
1263     CONTRACTL_END;
1264
1265     LookupContext sAltContext;
1266
1267     _ASSERTE((dac_cast<TADDR>(value) & IS_FIELD_MEMBER_REF) == 0);
1268
1269     MemberRefToDescHashEntry *pEntry = (PTR_MemberRefToDescHashEntry) BaseFindFirstEntryByHash(RidFromToken(token), &sAltContext);
1270     if (pEntry != NULL)
1271     {
1272         // 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.
1273         // However its value will be null. We need to set its actual value.
1274         if(pEntry->m_value == dac_cast<TADDR>(NULL))
1275         {
1276             EnsureWritablePages(&(pEntry->m_value));
1277             pEntry->m_value = dac_cast<TADDR>(value)|IS_FIELD_MEMBER_REF;
1278         }
1279
1280         _ASSERTE(pEntry->m_value == (dac_cast<TADDR>(value)|IS_FIELD_MEMBER_REF));
1281         return pEntry;
1282     }
1283
1284     // For non hot tokens insert new entry in hashtable
1285     pEntry = BaseAllocateEntry(NULL);
1286     pEntry->m_value = dac_cast<TADDR>(value)|IS_FIELD_MEMBER_REF;
1287     BaseInsertEntry(RidFromToken(token), pEntry);
1288
1289     return pEntry;
1290 }
1291
1292 // Insert MethodRef
1293 MemberRefToDescHashEntry* MemberRefToDescHashTable::Insert(mdMemberRef token , MethodDesc *value)
1294 {
1295     CONTRACTL
1296     {
1297         THROWS;
1298         GC_NOTRIGGER;
1299         MODE_ANY;
1300         INJECT_FAULT(COMPlusThrowOM(););
1301         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
1302     }
1303     CONTRACTL_END;
1304
1305     LookupContext sAltContext;
1306
1307     MemberRefToDescHashEntry *pEntry = (PTR_MemberRefToDescHashEntry) BaseFindFirstEntryByHash(RidFromToken(token), &sAltContext);
1308     if (pEntry != NULL)
1309     {
1310         // 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.
1311         // However its value will be null. We need to set its actual value.
1312         if(pEntry->m_value == dac_cast<TADDR>(NULL))
1313         {
1314             EnsureWritablePages(&(pEntry->m_value));
1315             pEntry->m_value = dac_cast<TADDR>(value);
1316         }
1317
1318         _ASSERTE(pEntry->m_value == dac_cast<TADDR>(value));
1319         return pEntry;
1320     }
1321
1322     // For non hot tokens insert new entry in hashtable
1323     pEntry = BaseAllocateEntry(NULL);
1324     pEntry->m_value = dac_cast<TADDR>(value);
1325     BaseInsertEntry(RidFromToken(token), pEntry);
1326
1327     return pEntry;
1328 }
1329
1330 #if defined(FEATURE_NATIVE_IMAGE_GENERATION)
1331 void MemberRefToDescHashTable::Save(DataImage *pImage, CorProfileData *pProfileData)
1332 {
1333     STANDARD_VM_CONTRACT;
1334
1335     // Mark if the tokens are hot
1336     if (pProfileData)
1337     {
1338         DWORD numInTokenList = pProfileData->GetHotTokens(mdtMemberRef>>24, 1<<RidMap, 1<<RidMap, NULL, 0);
1339         
1340         if (numInTokenList > 0)
1341         {
1342             LookupContext sAltContext;
1343
1344             mdToken *tokenList = (mdToken*)(void*)pImage->GetModule()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(mdToken)) * S_SIZE_T(numInTokenList));
1345
1346             pProfileData->GetHotTokens(mdtMemberRef>>24, 1<<RidMap, 1<<RidMap, tokenList, numInTokenList);
1347             for (DWORD i = 0; i < numInTokenList; i++)
1348             {
1349                 DWORD rid = RidFromToken(tokenList[i]);
1350                 MemberRefToDescHashEntry *pEntry = (PTR_MemberRefToDescHashEntry) BaseFindFirstEntryByHash(RidFromToken(tokenList[i]), &sAltContext);
1351                 if (pEntry != NULL)
1352                 {
1353                     _ASSERTE((pEntry->m_value & 0x1) == 0);
1354                     pEntry->m_value |= 0x1;
1355                 }
1356             }
1357         }
1358     }
1359
1360     BaseSave(pImage, pProfileData);
1361 }
1362
1363 void MemberRefToDescHashTable::FixupEntry(DataImage *pImage, MemberRefToDescHashEntry *pEntry, void *pFixupBase, DWORD cbFixupOffset)
1364 {
1365     //As there is no more hard binding initialize MemberRef* to NULL
1366     pImage->ZeroPointerField(pFixupBase, cbFixupOffset + offsetof(MemberRefToDescHashEntry, m_value));
1367 }
1368
1369 #endif // FEATURE_NATIVE_IMAGE_GENERATION
1370
1371 #endif // !DACCESS_COMPILE
1372
1373 PTR_MemberRef MemberRefToDescHashTable::GetValue(mdMemberRef token, BOOL *pfIsMethod)
1374 {
1375     CONTRACTL
1376     {
1377         NOTHROW;
1378         GC_NOTRIGGER;
1379         MODE_ANY;
1380         SUPPORTS_DAC;
1381     }
1382     CONTRACTL_END;
1383
1384     LookupContext sAltContext;
1385
1386     MemberRefToDescHashEntry *pEntry = (PTR_MemberRefToDescHashEntry) BaseFindFirstEntryByHash(RidFromToken(token), &sAltContext);
1387     if (pEntry != NULL)
1388     {
1389         if(pEntry->m_value & IS_FIELD_MEMBER_REF)
1390             *pfIsMethod = FALSE;
1391         else
1392             *pfIsMethod = TRUE;
1393         return (PTR_MemberRef)(pEntry->m_value & (~MEMBER_REF_MAP_ALL_FLAGS));
1394     }
1395
1396     return NULL;
1397 }
1398
1399
1400 void Module::SetDebuggerInfoBits(DebuggerAssemblyControlFlags newBits)
1401 {
1402     LIMITED_METHOD_CONTRACT;
1403     SUPPORTS_DAC;
1404
1405     _ASSERTE(((newBits << DEBUGGER_INFO_SHIFT_PRIV) &
1406               ~DEBUGGER_INFO_MASK_PRIV) == 0);
1407
1408     m_dwTransientFlags &= ~DEBUGGER_INFO_MASK_PRIV;
1409     m_dwTransientFlags |= (newBits << DEBUGGER_INFO_SHIFT_PRIV);
1410
1411 #ifdef DEBUGGING_SUPPORTED 
1412     BOOL setEnC = ((newBits & DACF_ENC_ENABLED) != 0) && IsEditAndContinueCapable();
1413
1414     // IsEditAndContinueCapable should already check !GetAssembly()->IsDomainNeutral
1415     _ASSERTE(!setEnC || !GetAssembly()->IsDomainNeutral());
1416
1417     // The only way can change Enc is through debugger override.
1418     if (setEnC)
1419     {
1420         EnableEditAndContinue();
1421     }
1422     else
1423     {
1424         if (!g_pConfig->ForceEnc())
1425             DisableEditAndContinue();
1426     }
1427 #endif // DEBUGGING_SUPPORTED
1428
1429 #if defined(DACCESS_COMPILE)
1430     // Now that we've changed m_dwTransientFlags, update that in the target too.
1431     // This will fail for read-only target.
1432     // If this fails, it will throw an exception.
1433     // @dbgtodo dac write: finalize on plans for how DAC writes to the target.
1434     HRESULT hrDac;
1435     hrDac = DacWriteHostInstance(this, true);
1436     _ASSERTE(SUCCEEDED(hrDac)); // would throw if there was an error.
1437 #endif // DACCESS_COMPILE
1438 }
1439
1440 #ifndef DACCESS_COMPILE
1441 /* static */
1442 Module *Module::Create(Assembly *pAssembly, mdFile moduleRef, PEFile *file, AllocMemTracker *pamTracker)
1443 {
1444     CONTRACT(Module *)
1445     {
1446         STANDARD_VM_CHECK;
1447         PRECONDITION(CheckPointer(pAssembly));
1448         PRECONDITION(CheckPointer(file));
1449         PRECONDITION(!IsNilToken(moduleRef) || file->IsAssembly());
1450         POSTCONDITION(CheckPointer(RETVAL));
1451         POSTCONDITION(RETVAL->GetFile() == file);
1452     }
1453     CONTRACT_END;
1454
1455     // Hoist CONTRACT into separate routine because of EX incompatibility
1456
1457     Module *pModule = NULL;
1458
1459     // Create the module
1460
1461 #ifdef FEATURE_PREJIT 
1462
1463     if (file->HasNativeImage())
1464     {
1465         pModule = file->GetLoadedNative()->GetPersistedModuleImage();
1466         PREFIX_ASSUME(pModule != NULL);
1467         CONSISTENCY_CHECK_MSG(pModule->m_pAssembly == NULL || !pModule->IsTenured(), // if the module is not tenured it could be our previous attempt
1468                               "Native image can only be used once per process\n");
1469         EnsureWritablePages(pModule);
1470         pModule = new ((void*) pModule) Module(pAssembly, moduleRef, file);
1471         PREFIX_ASSUME(pModule != NULL);
1472     }
1473
1474 #endif // FEATURE_PREJIT
1475
1476     if (pModule == NULL)
1477     {
1478 #ifdef EnC_SUPPORTED
1479         if (IsEditAndContinueCapable(pAssembly, file))
1480         {
1481             // IsEditAndContinueCapable should already check !pAssembly->IsDomainNeutral
1482             _ASSERTE(!pAssembly->IsDomainNeutral());
1483             
1484             // if file is EnCCapable, always create an EnC-module, but EnC won't necessarily be enabled.
1485             // Debugger enables this by calling SetJITCompilerFlags on LoadModule callback.
1486
1487             void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(EditAndContinueModule))));
1488             pModule = new (pMemory) EditAndContinueModule(pAssembly, moduleRef, file);
1489         }
1490         else
1491 #endif // EnC_SUPPORTED
1492         {
1493             void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(Module))));
1494             pModule = new (pMemory) Module(pAssembly, moduleRef, file);
1495         }
1496     }
1497
1498     PREFIX_ASSUME(pModule != NULL);
1499     ModuleHolder pModuleSafe(pModule);
1500     pModuleSafe->DoInit(pamTracker, NULL);
1501
1502     RETURN pModuleSafe.Extract();
1503 }
1504
1505 void Module::ApplyMetaData()
1506 {
1507     CONTRACTL
1508     {
1509         THROWS;
1510         GC_NOTRIGGER;
1511         MODE_ANY;
1512     }
1513     CONTRACTL_END;
1514
1515     LOG((LF_CLASSLOADER, LL_INFO100, "Module::ApplyNewMetaData %x\n", this));
1516
1517     HRESULT hr = S_OK;
1518     ULONG ulCount;
1519
1520     // Ensure for TypeRef
1521     ulCount = GetMDImport()->GetCountWithTokenKind(mdtTypeRef) + 1;
1522     EnsureTypeRefCanBeStored(TokenFromRid(ulCount, mdtTypeRef));
1523
1524     // Ensure for AssemblyRef
1525     ulCount = GetMDImport()->GetCountWithTokenKind(mdtAssemblyRef) + 1;
1526     EnsureAssemblyRefCanBeStored(TokenFromRid(ulCount, mdtAssemblyRef));
1527 }
1528
1529 //
1530 // Destructor for Module
1531 //
1532
1533 void Module::Destruct()
1534 {
1535     CONTRACTL
1536     {
1537         INSTANCE_CHECK;
1538         NOTHROW;
1539         GC_TRIGGERS;
1540         MODE_PREEMPTIVE;
1541     }
1542     CONTRACTL_END;
1543
1544     LOG((LF_EEMEM, INFO3, "Deleting module %x\n", this));
1545 #ifdef PROFILING_SUPPORTED
1546     {
1547         BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
1548         if (!IsBeingUnloaded())
1549         {
1550             // Profiler is causing some peripheral class loads. Probably this just needs
1551             // to be turned into a Fault_not_fatal and moved to a specific place inside the profiler.
1552             EX_TRY
1553             {
1554                 GCX_PREEMP();
1555                 g_profControlBlock.pProfInterface->ModuleUnloadStarted((ModuleID) this);
1556             }
1557             EX_CATCH
1558             {
1559             }
1560             EX_END_CATCH(SwallowAllExceptions);
1561         }
1562         END_PIN_PROFILER();
1563     }
1564 #endif // PROFILING_SUPPORTED
1565
1566
1567     DACNotify::DoModuleUnloadNotification(this);
1568
1569     // Free classes in the class table
1570     FreeClassTables();
1571     
1572
1573 #if defined(FEATURE_REMOTING) && !defined(HAS_REMOTING_PRECODE)
1574     // Destroys thunks for all methods included in hash table.
1575     if (m_pInstMethodHashTable != NULL)
1576     {
1577         InstMethodHashTable::Iterator it(m_pInstMethodHashTable);
1578         InstMethodHashEntry *pEntry;
1579
1580         while (m_pInstMethodHashTable->FindNext(&it, &pEntry))
1581         {
1582             MethodDesc *pMD = pEntry->GetMethod();
1583             if (!pMD->IsRestored())
1584                 continue;
1585
1586             if(pMD->GetMethodTable()->IsMarshaledByRef())
1587                 CRemotingServices::DestroyThunk(pMD);
1588         }
1589     }
1590 #endif // FEATURE_REMOTING && !HAS_REMOTING_PRECODE
1591
1592 #ifdef DEBUGGING_SUPPORTED 
1593     if (g_pDebugInterface)
1594     {
1595         GCX_PREEMP();
1596         g_pDebugInterface->DestructModule(this);
1597     }
1598
1599 #endif // DEBUGGING_SUPPORTED
1600
1601     ReleaseISymUnmanagedReader();
1602
1603     // Clean up sig cookies
1604     VASigCookieBlock    *pVASigCookieBlock = m_pVASigCookieBlock;
1605     while (pVASigCookieBlock)
1606     {
1607         VASigCookieBlock    *pNext = pVASigCookieBlock->m_Next;
1608         delete pVASigCookieBlock;
1609
1610         pVASigCookieBlock = pNext;
1611     }
1612
1613     // Clean up the IL stub cache
1614     if (m_pILStubCache != NULL)
1615     {
1616         delete m_pILStubCache;
1617     }
1618
1619 #ifdef FEATURE_MIXEDMODE // IJW
1620     delete m_pMUThunkHash;
1621     delete m_pThunkHeap;
1622 #endif // FEATURE_MIXEDMODE // IJW
1623
1624
1625 #ifdef PROFILING_SUPPORTED 
1626     {
1627         BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
1628         // Profiler is causing some peripheral class loads. Probably this just needs
1629         // to be turned into a Fault_not_fatal and moved to a specific place inside the profiler.
1630         EX_TRY
1631         {
1632             GCX_PREEMP();
1633             g_profControlBlock.pProfInterface->ModuleUnloadFinished((ModuleID) this, S_OK);
1634         }
1635         EX_CATCH
1636         {
1637         }
1638         EX_END_CATCH(SwallowAllExceptions);
1639         END_PIN_PROFILER();
1640     }
1641
1642     if (m_pValidatedEmitter.Load() != NULL)
1643     {
1644         m_pValidatedEmitter->Release();
1645     }
1646 #endif // PROFILING_SUPPORTED
1647
1648     //
1649     // Warning - deleting the zap file will cause the module to be unmapped
1650     //
1651     ClearInMemorySymbolStream();
1652
1653     m_Crst.Destroy();
1654     m_FixupCrst.Destroy();
1655     m_LookupTableCrst.Destroy();
1656     m_InstMethodHashTableCrst.Destroy();
1657     m_ISymUnmanagedReaderCrst.Destroy();
1658
1659 #ifdef FEATURE_CER
1660     if (m_pCerPrepInfo)
1661     {
1662         _ASSERTE(m_pCerCrst != NULL);
1663         CrstHolder sCrstHolder(m_pCerCrst);
1664
1665         EEHashTableIteration sIter;
1666         m_pCerPrepInfo->IterateStart(&sIter);
1667         while (m_pCerPrepInfo->IterateNext(&sIter)) {
1668             CerPrepInfo *pPrepInfo = (CerPrepInfo*)m_pCerPrepInfo->IterateGetValue(&sIter);
1669             delete pPrepInfo;
1670         }
1671
1672         delete m_pCerPrepInfo;
1673     }
1674     if (m_pCerCrst)
1675         delete m_pCerCrst;
1676 #endif // FEATURE_CER
1677
1678     if (m_debuggerSpecificData.m_pDynamicILCrst)
1679     {
1680         delete m_debuggerSpecificData.m_pDynamicILCrst;
1681     }
1682
1683     if (m_debuggerSpecificData.m_pDynamicILBlobTable)
1684     {
1685         delete m_debuggerSpecificData.m_pDynamicILBlobTable;
1686     }
1687
1688     if (m_debuggerSpecificData.m_pTemporaryILBlobTable)
1689     {
1690         delete m_debuggerSpecificData.m_pTemporaryILBlobTable;
1691     }
1692
1693     if (m_debuggerSpecificData.m_pILOffsetMappingTable)
1694     {
1695         for (ILOffsetMappingTable::Iterator pCurElem = m_debuggerSpecificData.m_pILOffsetMappingTable->Begin(),
1696                                             pEndElem = m_debuggerSpecificData.m_pILOffsetMappingTable->End();
1697              pCurElem != pEndElem;
1698              pCurElem++)
1699         {
1700             ILOffsetMappingEntry entry = *pCurElem;
1701             entry.m_mapping.Clear();
1702         }
1703         delete m_debuggerSpecificData.m_pILOffsetMappingTable;
1704     }
1705
1706 #ifdef FEATURE_PREJIT 
1707 #ifdef FEATURE_CER
1708     if (m_pCerNgenRootTable && (m_dwTransientFlags & M_CER_ROOT_TABLE_ON_HEAP))
1709         delete m_pCerNgenRootTable;
1710 #endif
1711
1712     if (HasNativeImage())
1713     {
1714         m_file->Release();
1715     }
1716     else
1717 #endif // FEATURE_PREJIT
1718     {
1719         m_file->Release();
1720
1721         if (m_pModuleSecurityDescriptor)
1722             delete m_pModuleSecurityDescriptor;
1723     }
1724
1725     // If this module was loaded as domain-specific, then 
1726     // we must free its ModuleIndex so that it can be reused
1727     FreeModuleIndex();
1728 }
1729
1730 #ifdef  FEATURE_PREJIT
1731 void Module::DeleteNativeCodeRanges()
1732 {
1733     CONTRACTL
1734     {
1735         NOTHROW;
1736         GC_NOTRIGGER;
1737         MODE_PREEMPTIVE;
1738         FORBID_FAULT;
1739     }
1740     CONTRACTL_END;
1741
1742     if (HasNativeImage())
1743     {
1744         PEImageLayout * pNativeImage = GetNativeImage();
1745
1746         ExecutionManager::DeleteRange(dac_cast<TADDR>(pNativeImage->GetBase()));
1747     }
1748 }
1749 #endif
1750
1751 bool Module::NeedsGlobalMethodTable()
1752 {
1753     CONTRACTL
1754     {
1755         INSTANCE_CHECK;
1756         THROWS;
1757         GC_TRIGGERS;
1758         MODE_ANY;
1759     }
1760     CONTRACTL_END;
1761
1762     IMDInternalImport * pImport = GetMDImport();
1763     if (!IsResource() && pImport->IsValidToken(COR_GLOBAL_PARENT_TOKEN))
1764     {
1765         {
1766             HENUMInternalHolder funcEnum(pImport);
1767             funcEnum.EnumGlobalFunctionsInit();
1768             if (pImport->EnumGetCount(&funcEnum) != 0)
1769                 return true;
1770         }
1771
1772         {
1773             HENUMInternalHolder fieldEnum(pImport);
1774             fieldEnum.EnumGlobalFieldsInit();
1775             if (pImport->EnumGetCount(&fieldEnum) != 0)
1776                 return true;
1777         }
1778     }
1779
1780     // resource module or no global statics nor global functions
1781     return false;
1782 }
1783
1784
1785 MethodTable *Module::GetGlobalMethodTable()
1786 {
1787     CONTRACT (MethodTable *)
1788     {
1789         INSTANCE_CHECK;
1790         THROWS;
1791         GC_TRIGGERS;
1792         MODE_ANY;
1793         INJECT_FAULT(CONTRACT_RETURN NULL;);
1794         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
1795     }
1796     CONTRACT_END;
1797
1798
1799     if ((m_dwPersistedFlags & COMPUTED_GLOBAL_CLASS) == 0)
1800     {
1801         MethodTable *pMT = NULL;
1802
1803         if (NeedsGlobalMethodTable())
1804         {
1805             pMT = ClassLoader::LoadTypeDefThrowing(this, COR_GLOBAL_PARENT_TOKEN,
1806                                                    ClassLoader::ThrowIfNotFound,
1807                                                    ClassLoader::FailIfUninstDefOrRef).AsMethodTable();
1808         }
1809
1810         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_GLOBAL_CLASS);
1811         RETURN pMT;
1812     }
1813     else
1814     {
1815         RETURN LookupTypeDef(COR_GLOBAL_PARENT_TOKEN).AsMethodTable();
1816     }
1817 }
1818
1819
1820 #endif // !DACCESS_COMPILE
1821
1822 #ifdef FEATURE_PREJIT 
1823
1824 /*static*/
1825 BOOL Module::IsAlwaysSavedInPreferredZapModule(Instantiation classInst,     // the type arguments to the type (if any)
1826                                                Instantiation methodInst)    // the type arguments to the method (if any)
1827 {
1828     LIMITED_METHOD_CONTRACT;
1829
1830     return ClassLoader::IsTypicalSharedInstantiation(classInst) &&
1831            ClassLoader::IsTypicalSharedInstantiation(methodInst);
1832 }
1833
1834 //this gets called recursively for generics, so do a probe.
1835 PTR_Module Module::ComputePreferredZapModule(Module * pDefinitionModule,
1836                                              Instantiation classInst,
1837                                              Instantiation methodInst)
1838 {
1839     CONTRACTL
1840     {
1841         NOTHROW;
1842         GC_NOTRIGGER;
1843         MODE_ANY;
1844         SO_TOLERANT;
1845         SUPPORTS_DAC;
1846     }
1847     CONTRACTL_END;
1848
1849     PTR_Module  ret = NULL;
1850     INTERIOR_STACK_PROBE_NOTHROW_CHECK_THREAD(DontCallDirectlyForceStackOverflow());
1851
1852     ret = Module::ComputePreferredZapModuleHelper( pDefinitionModule,
1853                                                    classInst,
1854                                                    methodInst );
1855     END_INTERIOR_STACK_PROBE;
1856     return ret;
1857 }
1858
1859 //
1860 // Is pModule likely a dependency of pOtherModule? Heuristic used by preffered zap module algorithm.
1861 // It can return both false positives and negatives.
1862 //
1863 static bool IsLikelyDependencyOf(Module * pModule, Module * pOtherModule)
1864 {
1865     CONTRACTL
1866     {
1867         NOTHROW;
1868         GC_NOTRIGGER;
1869         FORBID_FAULT;
1870         MODE_ANY;
1871         SUPPORTS_DAC;
1872         PRECONDITION(CheckPointer(pOtherModule));
1873     }
1874     CONTRACTL_END
1875     
1876     // Every module has a dependency with itself
1877     if (pModule == pOtherModule)
1878         return true;
1879
1880     //
1881     // Explicit check for low level system assemblies is working around Win8P facades introducing extra layer between low level system assemblies
1882     // (System.dll or System.Core.dll) and the app assemblies. Because of this extra layer, the check below won't see the direct
1883     // reference between these low level system assemblies and the app assemblies. The prefererred zap module for instantiations of generic
1884     // collections from these low level system assemblies (like LinkedList<AppType>) should be module of AppType. It would be module of the generic 
1885     // collection without this check. On desktop (FEATURE_FULL_NGEN defined), it would result into inefficient code because of the instantiations 
1886     // would be speculative. On CoreCLR (FEATURE_FULL_NGEN not defined), it would result into the instantiations not getting saved into native
1887     // image at all.
1888     //
1889     // Similar problem exists for Windows.Foundation.winmd. There is a cycle between Windows.Foundation.winmd and Windows.Storage.winmd. This cycle
1890     // would cause prefererred zap module for instantiations of foundation types (like IAsyncOperation<StorageFolder>) to be Windows.Foundation.winmd.
1891     // It is a bad choice. It should be Windows.Storage.winmd instead. We explicitly push Windows.Foundation to lower level by treating it as 
1892     // low level system assembly to avoid this problem.
1893     //
1894     if (pModule->IsLowLevelSystemAssemblyByName())
1895     {
1896         if (!pOtherModule->IsLowLevelSystemAssemblyByName())
1897             return true;
1898
1899         // Every module depends upon mscorlib
1900         if (pModule->IsSystem())
1901             return true;
1902
1903         // mscorlib does not depend upon any other module
1904         if (pOtherModule->IsSystem())
1905             return false;
1906     }
1907     else
1908     {
1909         if (pOtherModule->IsLowLevelSystemAssemblyByName())
1910             return false;
1911     }
1912
1913     // At this point neither pModule or pOtherModule is mscorlib
1914
1915 #ifndef DACCESS_COMPILE 
1916     //
1917     // We will check to see if the pOtherModule has a reference to pModule
1918     //
1919
1920     // If we can match the assembly ref in the ManifestModuleReferencesMap we can early out.
1921     // This early out kicks in less than half of the time. It hurts performance on average.
1922     // if (!IsNilToken(pOtherModule->FindAssemblyRef(pModule->GetAssembly())))
1923     //     return true;
1924
1925     if (pOtherModule->HasReferenceByName(pModule->GetSimpleName()))
1926         return true;
1927 #endif // DACCESS_COMPILE
1928
1929     return false;
1930 }
1931
1932 // Determine the "preferred ngen home" for an instantiated type or method
1933 // * This is the first ngen module that the loader will look in;
1934 // * Also, we only hard bind to a type or method that lives in its preferred module
1935 // The following properties must hold of the preferred module:
1936 // - it must be one of the component type's declaring modules
1937 // - if the type or method is open then the preferred module must be that of one of the type parameters
1938 //   (this ensures that we can always hard bind to open types and methods created during ngen)
1939 // - for always-saved instantiations it must be the declaring module of the generic definition
1940 // Otherwise, we try to pick a module that is likely to reference the type or method
1941 //
1942 /* static */
1943 PTR_Module Module::ComputePreferredZapModuleHelper(
1944     Module * pDefinitionModule,    // the module that declares the generic type or method
1945     Instantiation classInst,       // the type arguments to the type (if any)
1946     Instantiation methodInst)      // the type arguments to the method (if any)
1947 {
1948     CONTRACT(PTR_Module)
1949     {
1950         NOTHROW;
1951         GC_NOTRIGGER;
1952         FORBID_FAULT;
1953         MODE_ANY;
1954         PRECONDITION(CheckPointer(pDefinitionModule, NULL_OK));
1955         // One of them will be non-null... Note we don't use CheckPointer
1956         // because that raises a breakpoint in the debugger
1957         PRECONDITION(pDefinitionModule != NULL || !classInst.IsEmpty() || !methodInst.IsEmpty());
1958         POSTCONDITION(CheckPointer(RETVAL));
1959         SUPPORTS_DAC;
1960     }
1961     CONTRACT_END
1962
1963     DWORD totalArgs = classInst.GetNumArgs() + methodInst.GetNumArgs();
1964
1965     // The open type parameters takes precendence over closed type parameters since
1966     // we always hardbind to open types.
1967     for (DWORD i = 0; i < totalArgs; i++)
1968     {
1969         TypeHandle thArg = (i < classInst.GetNumArgs()) ? classInst[i] : methodInst[i - classInst.GetNumArgs()];
1970
1971         // Encoded types are never open
1972         _ASSERTE(!thArg.IsEncodedFixup());
1973         Module * pOpenModule = thArg.GetDefiningModuleForOpenType();
1974         if (pOpenModule != NULL)
1975             RETURN dac_cast<PTR_Module>(pOpenModule);
1976     }
1977
1978     // The initial value of pCurrentPZM is the pDefinitionModule or mscorlib 
1979     Module* pCurrentPZM = (pDefinitionModule != NULL) ? pDefinitionModule : MscorlibBinder::GetModule();
1980     bool preferredZapModuleBasedOnValueType = false;
1981
1982     for (DWORD i = 0; i < totalArgs; i++)
1983     {
1984         TypeHandle pTypeParam = (i < classInst.GetNumArgs()) ? classInst[i] : methodInst[i - classInst.GetNumArgs()];
1985
1986         _ASSERTE(pTypeParam != NULL);
1987         _ASSERTE(!pTypeParam.IsEncodedFixup()); 
1988
1989         Module * pParamPZM = GetPreferredZapModuleForTypeHandle(pTypeParam);
1990
1991         //
1992         // If pCurrentPZM is not a dependency of pParamPZM
1993         // then we aren't going to update pCurrentPZM
1994         // 
1995         if (IsLikelyDependencyOf(pCurrentPZM, pParamPZM))
1996         {
1997             // If we have a type parameter that is a value type 
1998             // and we don't yet have a value type based pCurrentPZM
1999             // then we will select it's module as the new pCurrentPZM.
2000             //
2001             if (pTypeParam.IsValueType() && !preferredZapModuleBasedOnValueType)
2002             {
2003                 pCurrentPZM = pParamPZM;
2004                 preferredZapModuleBasedOnValueType = true;
2005             }
2006             else
2007             {
2008                 // The normal rule is to replace the pCurrentPZM only when 
2009                 // both of the following are true:
2010                 //     pCurrentPZM is a dependency of pParamPZM 
2011                 // and pParamPZM is not a dependency of pCurrentPZM
2012                 // 
2013                 // note that the second condition is alway true when pCurrentPZM is mscorlib
2014                 //
2015                 if (!IsLikelyDependencyOf(pParamPZM, pCurrentPZM))
2016                 {
2017                     pCurrentPZM = pParamPZM;
2018                 }
2019             }
2020         }
2021     }
2022
2023     RETURN dac_cast<PTR_Module>(pCurrentPZM);
2024 }
2025
2026 PTR_Module Module::ComputePreferredZapModule(TypeKey *pKey)
2027 {
2028     CONTRACTL
2029     {
2030         NOTHROW;
2031         GC_NOTRIGGER;
2032         SO_TOLERANT;
2033         MODE_ANY;
2034         SUPPORTS_DAC;
2035     }
2036     CONTRACTL_END;
2037
2038     if (pKey->GetKind() == ELEMENT_TYPE_CLASS)
2039     {
2040         return Module::ComputePreferredZapModule(pKey->GetModule(),
2041                                                  pKey->GetInstantiation());
2042     }
2043     else if (pKey->GetKind() != ELEMENT_TYPE_FNPTR)
2044         return Module::GetPreferredZapModuleForTypeHandle(pKey->GetElementType());
2045     else
2046         return NULL;
2047
2048 }
2049
2050 /* see code:Module::ComputePreferredZapModuleHelper for more */
2051 /*static*/
2052 PTR_Module Module::GetPreferredZapModuleForMethodTable(MethodTable *pMT)
2053 {
2054     CONTRACTL
2055     {
2056         NOTHROW;
2057         GC_NOTRIGGER;
2058         SO_TOLERANT;
2059         MODE_ANY;
2060         SUPPORTS_DAC;
2061     }
2062     CONTRACTL_END;
2063
2064     PTR_Module pRet=NULL;
2065
2066     INTERIOR_STACK_PROBE_FOR_NOTHROW_CHECK_THREAD(10, NO_FORBIDGC_LOADER_USE_ThrowSO(););
2067
2068     if (pMT->IsArray())
2069     {
2070         TypeHandle elemTH = pMT->GetApproxArrayElementTypeHandle();
2071         pRet= ComputePreferredZapModule(NULL, Instantiation(&elemTH, 1));
2072     }
2073     else if (pMT->HasInstantiation() && !pMT->IsGenericTypeDefinition())
2074     {
2075         pRet= ComputePreferredZapModule(pMT->GetModule(),
2076                                         pMT->GetInstantiation());
2077     }
2078     else
2079     {
2080         // If it is uninstantiated or it is the generic type definition itself
2081         // then its loader module is simply the module containing its TypeDef
2082         pRet= pMT->GetModule();
2083     }
2084     END_INTERIOR_STACK_PROBE;
2085     return pRet;
2086 }
2087
2088
2089 /*static*/
2090 PTR_Module Module::GetPreferredZapModuleForTypeDesc(PTR_TypeDesc pTD)
2091 {
2092     CONTRACTL
2093     {
2094         NOTHROW;
2095         GC_NOTRIGGER;
2096         SO_TOLERANT;
2097         MODE_ANY;
2098     }
2099     CONTRACTL_END;
2100     SUPPORTS_DAC;
2101     if (pTD->HasTypeParam())
2102         return GetPreferredZapModuleForTypeHandle(pTD->GetTypeParam());
2103     else if (pTD->IsGenericVariable())
2104         return pTD->GetModule();
2105
2106     _ASSERTE(pTD->GetInternalCorElementType() == ELEMENT_TYPE_FNPTR);
2107     PTR_FnPtrTypeDesc pFnPtrTD = dac_cast<PTR_FnPtrTypeDesc>(pTD);
2108
2109     // Result type of function type is used for preferred zap module
2110     return GetPreferredZapModuleForTypeHandle(pFnPtrTD->GetRetAndArgTypesPointer()[0]);
2111 }
2112
2113 /*static*/
2114 PTR_Module Module::GetPreferredZapModuleForTypeHandle(TypeHandle t)
2115 {
2116     CONTRACTL
2117     {
2118         NOTHROW;
2119         GC_NOTRIGGER;
2120         SO_TOLERANT;
2121         MODE_ANY;
2122     }
2123     CONTRACTL_END;
2124     SUPPORTS_DAC;
2125     if (t.IsTypeDesc())
2126         return GetPreferredZapModuleForTypeDesc(t.AsTypeDesc());
2127     else
2128         return GetPreferredZapModuleForMethodTable(t.AsMethodTable());
2129 }
2130
2131 /*static*/
2132 PTR_Module Module::GetPreferredZapModuleForMethodDesc(const MethodDesc *pMD)
2133 {
2134     CONTRACTL
2135     {
2136         NOTHROW;
2137         GC_NOTRIGGER;
2138         SO_TOLERANT;
2139         MODE_ANY;
2140     }
2141     CONTRACTL_END;
2142
2143     if (pMD->IsTypicalMethodDefinition())
2144     {
2145         return PTR_Module(pMD->GetModule());
2146     }
2147     else if (pMD->IsGenericMethodDefinition())
2148     {
2149         return GetPreferredZapModuleForMethodTable(pMD->GetMethodTable());
2150     }
2151     else
2152     {
2153         return ComputePreferredZapModule(pMD->GetModule(),
2154                                          pMD->GetClassInstantiation(), 
2155                                          pMD->GetMethodInstantiation());
2156     }
2157 }
2158
2159 /* see code:Module::ComputePreferredZapModuleHelper for more */
2160 /*static*/
2161 PTR_Module Module::GetPreferredZapModuleForFieldDesc(FieldDesc * pFD)
2162 {
2163     CONTRACTL
2164     {
2165         NOTHROW;
2166         GC_NOTRIGGER;
2167         SO_TOLERANT;
2168         MODE_ANY;
2169     }
2170     CONTRACTL_END;
2171
2172     // The approx MT is sufficient: it's always the one that owns the FieldDesc
2173     // data structure
2174     return GetPreferredZapModuleForMethodTable(pFD->GetApproxEnclosingMethodTable());
2175 }
2176 #endif // FEATURE_PREJIT
2177
2178 /*static*/
2179 BOOL Module::IsEditAndContinueCapable(Assembly *pAssembly, PEFile *file)
2180 {
2181     CONTRACTL
2182         {
2183             NOTHROW;
2184             GC_NOTRIGGER;
2185             SO_TOLERANT;
2186             MODE_ANY;
2187             SUPPORTS_DAC;
2188         }
2189     CONTRACTL_END;
2190
2191     _ASSERTE(pAssembly != NULL && file != NULL);
2192     
2193     // Some modules are never EnC-capable
2194     return ! (pAssembly->GetDebuggerInfoBits() & DACF_ALLOW_JIT_OPTS ||
2195               pAssembly->IsDomainNeutral() ||
2196               file->IsSystem() ||
2197               file->IsResource() ||
2198               file->HasNativeImage() ||
2199               file->IsDynamic());
2200 }
2201
2202 BOOL Module::IsManifest()
2203 {
2204     WRAPPER_NO_CONTRACT;
2205     return dac_cast<TADDR>(GetAssembly()->GetManifestModule()) ==
2206            dac_cast<TADDR>(this);
2207 }
2208
2209 DomainAssembly* Module::GetDomainAssembly(AppDomain *pDomain)
2210 {
2211     CONTRACT(DomainAssembly *)
2212     {
2213         INSTANCE_CHECK;
2214         PRECONDITION(CheckPointer(pDomain, NULL_OK));
2215         POSTCONDITION(CheckPointer(RETVAL));
2216         THROWS;
2217         GC_TRIGGERS;
2218         MODE_ANY;
2219     }
2220     CONTRACT_END;
2221
2222     if (IsManifest())
2223         RETURN (DomainAssembly *) GetDomainFile(pDomain);
2224     else
2225         RETURN (DomainAssembly *) m_pAssembly->GetDomainAssembly(pDomain);
2226 }
2227
2228 DomainFile *Module::GetDomainFile(AppDomain *pDomain)
2229 {
2230     CONTRACT(DomainFile *)
2231     {
2232         INSTANCE_CHECK;
2233         PRECONDITION(CheckPointer(pDomain));
2234         POSTCONDITION(CheckPointer(RETVAL));
2235         GC_TRIGGERS;
2236         THROWS;
2237         MODE_ANY;
2238         SUPPORTS_DAC;
2239     }
2240     CONTRACT_END;
2241
2242     if (Module::IsEncodedModuleIndex(GetModuleID()))
2243     {
2244         DomainLocalBlock *pLocalBlock = pDomain->GetDomainLocalBlock();
2245         DomainFile *pDomainFile =  pLocalBlock->TryGetDomainFile(GetModuleIndex());
2246
2247 #if !defined(DACCESS_COMPILE) && defined(FEATURE_LOADER_OPTIMIZATION)
2248         if (pDomainFile == NULL)
2249             pDomainFile = pDomain->LoadDomainNeutralModuleDependency(this, FILE_LOADED);
2250 #endif // !DACCESS_COMPILE
2251
2252         RETURN (PTR_DomainFile) pDomainFile;
2253     }
2254     else
2255     {
2256
2257         CONSISTENCY_CHECK(dac_cast<TADDR>(pDomain) == dac_cast<TADDR>(GetDomain()) || IsSingleAppDomain());
2258         RETURN dac_cast<PTR_DomainFile>(m_ModuleID->GetDomainFile());
2259     }
2260 }
2261
2262 DomainAssembly* Module::FindDomainAssembly(AppDomain *pDomain)
2263 {
2264     CONTRACT(DomainAssembly *)
2265     {
2266         INSTANCE_CHECK;
2267         PRECONDITION(CheckPointer(pDomain));
2268         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
2269         NOTHROW;
2270         GC_NOTRIGGER;
2271         MODE_ANY;
2272         SO_TOLERANT;
2273         SUPPORTS_DAC;
2274     }
2275     CONTRACT_END;
2276
2277     if (IsManifest())
2278         RETURN dac_cast<PTR_DomainAssembly>(FindDomainFile(pDomain));
2279     else
2280         RETURN m_pAssembly->FindDomainAssembly(pDomain);
2281 }
2282
2283 DomainModule *Module::GetDomainModule(AppDomain *pDomain)
2284 {
2285     CONTRACT(DomainModule *)
2286     {
2287         INSTANCE_CHECK;
2288         PRECONDITION(CheckPointer(pDomain));
2289         PRECONDITION(!IsManifest());
2290         POSTCONDITION(CheckPointer(RETVAL));
2291
2292         THROWS;
2293         GC_TRIGGERS;
2294         MODE_ANY;
2295     }
2296     CONTRACT_END;
2297
2298     RETURN (DomainModule *) GetDomainFile(pDomain);
2299 }
2300
2301 DomainFile *Module::FindDomainFile(AppDomain *pDomain)
2302 {
2303     CONTRACT(DomainFile *)
2304     {
2305         INSTANCE_CHECK;
2306         PRECONDITION(CheckPointer(pDomain));
2307         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
2308         NOTHROW;
2309         GC_NOTRIGGER;
2310         MODE_ANY;
2311         SO_TOLERANT;
2312         SUPPORTS_DAC;
2313     }
2314     CONTRACT_END;
2315
2316     if (Module::IsEncodedModuleIndex(GetModuleID()))
2317     {
2318         DomainLocalBlock *pLocalBlock = pDomain->GetDomainLocalBlock();
2319         RETURN pLocalBlock->TryGetDomainFile(GetModuleIndex());
2320     }
2321     else
2322     {
2323         if (dac_cast<TADDR>(pDomain) == dac_cast<TADDR>(GetDomain()) || IsSingleAppDomain())
2324             RETURN m_ModuleID->GetDomainFile();
2325         else
2326             RETURN NULL;
2327     }
2328 }
2329
2330 DomainModule *Module::FindDomainModule(AppDomain *pDomain)
2331 {
2332     CONTRACT(DomainModule *)
2333     {
2334         INSTANCE_CHECK;
2335         PRECONDITION(CheckPointer(pDomain));
2336         PRECONDITION(!IsManifest());
2337         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
2338         GC_NOTRIGGER;
2339         NOTHROW;
2340         MODE_ANY;
2341     }
2342     CONTRACT_END;
2343
2344     RETURN (DomainModule *) FindDomainFile(pDomain);
2345 }
2346
2347 #ifndef DACCESS_COMPILE 
2348 #include "staticallocationhelpers.inl"
2349
2350 // Parses metadata and initializes offsets of per-class static blocks.
2351 void Module::BuildStaticsOffsets(AllocMemTracker *pamTracker)
2352 {
2353     STANDARD_VM_CONTRACT;
2354
2355     // Trade off here. We want a slot for each type. That way we can get to 2 bits per class and
2356     // index directly and not need a mapping from ClassID to MethodTable (we will use the RID
2357     // as the mapping)
2358     IMDInternalImport *pImport = GetMDImport();
2359
2360     DWORD * pRegularStaticOffsets = NULL;
2361     DWORD * pThreadStaticOffsets = NULL;
2362
2363     // Get the number of types/classes defined in this module. Add 1 to count the module itself
2364     DWORD dwNumTypes   = pImport->GetCountWithTokenKind(mdtTypeDef) + 1; // +1 for module type
2365
2366     // [0] covers regular statics, [1] covers thread statics
2367     DWORD      dwGCHandles[2] = { 0, 0 };
2368
2369     // Organization in memory of the static block
2370     //
2371     //
2372     //                                       |  GC Statics             |
2373     //                                                  |
2374     //                                                  |
2375     //    | Class Data (one byte per class)  |   pointer to gc statics | primitive type statics |
2376     //
2377     //
2378     DWORD      dwNonGCBytes[2] = { 
2379         DomainLocalModule::OffsetOfDataBlob() + sizeof(BYTE)*dwNumTypes, 
2380         ThreadLocalModule::OffsetOfDataBlob() + sizeof(BYTE)*dwNumTypes
2381     };
2382
2383     HENUMInternalHolder hTypeEnum(pImport);
2384     hTypeEnum.EnumAllInit(mdtTypeDef);
2385
2386     mdTypeDef type;
2387     // Parse each type of the class
2388     while (pImport->EnumNext(&hTypeEnum, &type))
2389     {
2390         // Set offset for this type
2391         DWORD dwIndex = RidFromToken(type) - 1;
2392
2393         // [0] covers regular statics, [1] covers thread statics
2394         DWORD dwAlignment[2] = { 1, 1 };
2395         DWORD dwClassNonGCBytes[2] = { 0, 0 };
2396         DWORD dwClassGCHandles[2]  = { 0, 0 };
2397
2398         // need to check if the type is generic and if so exclude it from iteration as we don't know the size
2399         HENUMInternalHolder hGenericEnum(pImport);
2400         hGenericEnum.EnumInit(mdtGenericParam, type);
2401         ULONG cGenericParams = pImport->EnumGetCount(&hGenericEnum);
2402         if (cGenericParams == 0)
2403         {
2404             HENUMInternalHolder hFieldEnum(pImport);
2405             hFieldEnum.EnumInit(mdtFieldDef, type);
2406
2407             mdFieldDef field;
2408             // Parse each field of the type
2409             while (pImport->EnumNext(&hFieldEnum, &field))
2410             {
2411                 BOOL fSkip = FALSE;
2412
2413                 CorElementType ElementType = ELEMENT_TYPE_END;
2414                 mdToken tkValueTypeToken = 0;
2415                 int kk; // Use one set of variables for regular statics, and the other set for thread statics
2416                 
2417                 fSkip = GetStaticFieldElementTypeForFieldDef(this, pImport, field, &ElementType, &tkValueTypeToken, &kk);
2418                 if (fSkip)
2419                     continue;
2420
2421                 // We account for "regular statics" and "thread statics" separately. 
2422                 // Currently we are lumping RVA and context statics into "regular statics",
2423                 // but we probably shouldn't.
2424                 switch (ElementType)
2425                 {
2426                     case ELEMENT_TYPE_I1:
2427                     case ELEMENT_TYPE_U1:
2428                     case ELEMENT_TYPE_BOOLEAN:
2429                         dwClassNonGCBytes[kk] += 1;
2430                         break;
2431                     case ELEMENT_TYPE_I2:
2432                     case ELEMENT_TYPE_U2:
2433                     case ELEMENT_TYPE_CHAR:
2434                         dwAlignment[kk] =  max(2, dwAlignment[kk]);
2435                         dwClassNonGCBytes[kk] += 2;
2436                         break;
2437                     case ELEMENT_TYPE_I4:
2438                     case ELEMENT_TYPE_U4:
2439                     case ELEMENT_TYPE_R4:
2440                         dwAlignment[kk] =  max(4, dwAlignment[kk]);
2441                         dwClassNonGCBytes[kk] += 4;
2442                         break;
2443                     case ELEMENT_TYPE_FNPTR:
2444                     case ELEMENT_TYPE_PTR:
2445                     case ELEMENT_TYPE_I:
2446                     case ELEMENT_TYPE_U:
2447                         dwAlignment[kk] =  max((1 << LOG2_PTRSIZE), dwAlignment[kk]);
2448                         dwClassNonGCBytes[kk] += (1 << LOG2_PTRSIZE);
2449                         break;
2450                     case ELEMENT_TYPE_I8:
2451                     case ELEMENT_TYPE_U8:
2452                     case ELEMENT_TYPE_R8:
2453                         dwAlignment[kk] =  max(8, dwAlignment[kk]);
2454                         dwClassNonGCBytes[kk] += 8;
2455                         break;
2456                     case ELEMENT_TYPE_VAR:
2457                     case ELEMENT_TYPE_MVAR:
2458                     case ELEMENT_TYPE_STRING:
2459                     case ELEMENT_TYPE_SZARRAY:
2460                     case ELEMENT_TYPE_ARRAY:
2461                     case ELEMENT_TYPE_CLASS:
2462                     case ELEMENT_TYPE_OBJECT:
2463                         dwClassGCHandles[kk]  += 1;
2464                         break;
2465                     case ELEMENT_TYPE_VALUETYPE:
2466                         // Statics for valuetypes where the valuetype is defined in this module are handled here. Other valuetype statics utilize the pessimistic model below.
2467                         dwClassGCHandles[kk]  += 1;
2468                         break;
2469                     case ELEMENT_TYPE_END:
2470                     default:
2471                         // The actual element type was ELEMENT_TYPE_VALUETYPE, but the as we don't want to load additional assemblies
2472                         // to determine these static offsets, we've fallen back to a pessimistic model.
2473                         if (tkValueTypeToken != 0)
2474                         {
2475                             // We'll have to be pessimistic here
2476                             dwClassNonGCBytes[kk] += MAX_PRIMITIVE_FIELD_SIZE;
2477                             dwAlignment[kk] = max(MAX_PRIMITIVE_FIELD_SIZE, dwAlignment[kk]);
2478
2479                             dwClassGCHandles[kk]  += 1;
2480                             break;
2481                         }
2482                         else
2483                         {
2484                             // field has an unexpected type
2485                             ThrowHR(VER_E_FIELD_SIG);
2486                             break;
2487                         }
2488                 }
2489             }
2490
2491             if (pRegularStaticOffsets == NULL && (dwClassGCHandles[0] != 0 || dwClassNonGCBytes[0] != 0))
2492             {
2493                 // Lazily allocate table for offsets. We need offsets for GC and non GC areas. We add +1 to use as a sentinel. 
2494                 pRegularStaticOffsets = (PTR_DWORD)pamTracker->Track(
2495                     GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(
2496                         (S_SIZE_T(2 * sizeof(DWORD))*(S_SIZE_T(dwNumTypes)+S_SIZE_T(1)))));
2497
2498                 for (DWORD i = 0; i < dwIndex; i++) {
2499                     pRegularStaticOffsets[i * 2    ] = dwGCHandles[0]*sizeof(OBJECTREF);
2500                     pRegularStaticOffsets[i * 2 + 1] = dwNonGCBytes[0];                    
2501                 }
2502             }
2503
2504             if (pThreadStaticOffsets == NULL && (dwClassGCHandles[1] != 0 || dwClassNonGCBytes[1] != 0))
2505             {
2506                 // Lazily allocate table for offsets. We need offsets for GC and non GC areas. We add +1 to use as a sentinel. 
2507                 pThreadStaticOffsets = (PTR_DWORD)pamTracker->Track(
2508                     GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(
2509                         (S_SIZE_T(2 * sizeof(DWORD))*(S_SIZE_T(dwNumTypes)+S_SIZE_T(1)))));
2510
2511                 for (DWORD i = 0; i < dwIndex; i++) {
2512                     pThreadStaticOffsets[i * 2    ] = dwGCHandles[1]*sizeof(OBJECTREF);
2513                     pThreadStaticOffsets[i * 2 + 1] = dwNonGCBytes[1];                    
2514                 }
2515             }
2516         }
2517
2518         if (pRegularStaticOffsets != NULL)
2519         {
2520             // Align the offset of non gc statics
2521             dwNonGCBytes[0] = (DWORD) ALIGN_UP(dwNonGCBytes[0], dwAlignment[0]);
2522
2523             // Save current offsets
2524             pRegularStaticOffsets[dwIndex*2]     = dwGCHandles[0]*sizeof(OBJECTREF);
2525             pRegularStaticOffsets[dwIndex*2 + 1] = dwNonGCBytes[0];
2526         
2527             // Increment for next class
2528             dwGCHandles[0]  += dwClassGCHandles[0];
2529             dwNonGCBytes[0] += dwClassNonGCBytes[0];
2530         }
2531
2532         if (pThreadStaticOffsets != NULL)
2533         {
2534             // Align the offset of non gc statics
2535             dwNonGCBytes[1] = (DWORD) ALIGN_UP(dwNonGCBytes[1], dwAlignment[1]);
2536
2537             // Save current offsets
2538             pThreadStaticOffsets[dwIndex*2]     = dwGCHandles[1]*sizeof(OBJECTREF);
2539             pThreadStaticOffsets[dwIndex*2 + 1] = dwNonGCBytes[1];
2540         
2541             // Increment for next class
2542             dwGCHandles[1]  += dwClassGCHandles[1];
2543             dwNonGCBytes[1] += dwClassNonGCBytes[1];
2544         }
2545     }
2546
2547     m_maxTypeRidStaticsAllocated = dwNumTypes;
2548
2549     if (pRegularStaticOffsets != NULL)
2550     {
2551         pRegularStaticOffsets[dwNumTypes*2]     = dwGCHandles[0]*sizeof(OBJECTREF);
2552         pRegularStaticOffsets[dwNumTypes*2 + 1] = dwNonGCBytes[0];
2553     }
2554
2555     if (pThreadStaticOffsets != NULL)
2556     {
2557         pThreadStaticOffsets[dwNumTypes*2]     = dwGCHandles[1]*sizeof(OBJECTREF);
2558         pThreadStaticOffsets[dwNumTypes*2 + 1] = dwNonGCBytes[1];
2559     }
2560
2561     m_pRegularStaticOffsets = pRegularStaticOffsets;
2562     m_pThreadStaticOffsets = pThreadStaticOffsets;
2563
2564     m_dwMaxGCRegularStaticHandles = dwGCHandles[0];
2565     m_dwMaxGCThreadStaticHandles = dwGCHandles[1];
2566
2567     m_dwRegularStaticsBlockSize = dwNonGCBytes[0];
2568     m_dwThreadStaticsBlockSize = dwNonGCBytes[1];
2569 }
2570
2571 void  Module::GetOffsetsForRegularStaticData(
2572                     mdToken cl,
2573                     BOOL bDynamic, DWORD dwGCStaticHandles,
2574                     DWORD dwNonGCStaticBytes,
2575                     DWORD * pOutStaticHandleOffset,
2576                     DWORD * pOutNonGCStaticOffset)
2577 {
2578     CONTRACTL
2579     {
2580         THROWS;
2581         GC_TRIGGERS;
2582         INJECT_FAULT(COMPlusThrowOM());
2583     }
2584     CONTRACTL_END
2585
2586     *pOutStaticHandleOffset = 0;
2587     *pOutNonGCStaticOffset  = 0;
2588
2589     if (!dwGCStaticHandles && !dwNonGCStaticBytes)
2590     {
2591         return;
2592     }
2593
2594     // Statics for instantiated types are allocated dynamically per-instantiation
2595     if (bDynamic)
2596     {
2597         // Non GC statics are embedded in the Dynamic Entry.
2598         *pOutNonGCStaticOffset  = DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob();
2599         return;
2600     }
2601
2602     if (m_pRegularStaticOffsets == NULL)
2603     {
2604         THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
2605     }
2606     _ASSERTE(m_pRegularStaticOffsets != (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED);
2607
2608     // We allocate in the big blob.
2609     DWORD index = RidFromToken(cl) - 1;
2610
2611     *pOutStaticHandleOffset = m_pRegularStaticOffsets[index*2];
2612
2613     *pOutNonGCStaticOffset  = m_pRegularStaticOffsets[index*2 + 1];
2614
2615     // Check we didnt go out of what we predicted we would need for the class
2616     if (*pOutStaticHandleOffset + sizeof(OBJECTREF*)*dwGCStaticHandles >
2617                 m_pRegularStaticOffsets[(index+1)*2] ||
2618         *pOutNonGCStaticOffset + dwNonGCStaticBytes >
2619                 m_pRegularStaticOffsets[(index+1)*2 + 1])
2620     {   // It's most likely that this is due to bad metadata, thus the exception. However, the
2621         // previous comments for this bit of code mentioned that this could be a corner case bug
2622         // with static field size estimation, though this is entirely unlikely since the code has
2623         // been this way for at least two releases.
2624         THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
2625     }
2626 }
2627
2628
2629 void  Module::GetOffsetsForThreadStaticData(
2630                     mdToken cl,
2631                     BOOL bDynamic, DWORD dwGCStaticHandles,
2632                     DWORD dwNonGCStaticBytes,
2633                     DWORD * pOutStaticHandleOffset,
2634                     DWORD * pOutNonGCStaticOffset)
2635 {
2636     CONTRACTL
2637     {
2638         THROWS;
2639         GC_TRIGGERS;
2640         INJECT_FAULT(COMPlusThrowOM());
2641     }
2642     CONTRACTL_END
2643
2644     *pOutStaticHandleOffset = 0;
2645     *pOutNonGCStaticOffset  = 0;
2646
2647     if (!dwGCStaticHandles && !dwNonGCStaticBytes)
2648     {
2649         return;
2650     }
2651
2652     // Statics for instantiated types are allocated dynamically per-instantiation
2653     if (bDynamic)
2654     {
2655         // Non GC thread statics are embedded in the Dynamic Entry.
2656         *pOutNonGCStaticOffset  = ThreadLocalModule::DynamicEntry::GetOffsetOfDataBlob();
2657         return;
2658     }
2659
2660     if (m_pThreadStaticOffsets == NULL)
2661     {
2662         THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
2663     }
2664     _ASSERTE(m_pThreadStaticOffsets != (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED);
2665
2666     // We allocate in the big blob.
2667     DWORD index = RidFromToken(cl) - 1;
2668
2669     *pOutStaticHandleOffset = m_pThreadStaticOffsets[index*2];
2670
2671     *pOutNonGCStaticOffset  = m_pThreadStaticOffsets[index*2 + 1];
2672
2673     // Check we didnt go out of what we predicted we would need for the class
2674     if (*pOutStaticHandleOffset + sizeof(OBJECTREF*)*dwGCStaticHandles >
2675                 m_pThreadStaticOffsets[(index+1)*2] ||
2676         *pOutNonGCStaticOffset + dwNonGCStaticBytes >
2677                 m_pThreadStaticOffsets[(index+1)*2 + 1])
2678     {
2679         // It's most likely that this is due to bad metadata, thus the exception. However, the
2680         // previous comments for this bit of code mentioned that this could be a corner case bug
2681         // with static field size estimation, though this is entirely unlikely since the code has
2682         // been this way for at least two releases.
2683         THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
2684     }
2685 }
2686
2687
2688 // initialize Crst controlling the Dynamic IL hashtable
2689 void Module::InitializeDynamicILCrst()
2690 {
2691     Crst * pCrst = new Crst(CrstDynamicIL, CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD));
2692     if (InterlockedCompareExchangeT(
2693             &m_debuggerSpecificData.m_pDynamicILCrst, pCrst, NULL) != NULL)
2694     {
2695         delete pCrst;
2696     }
2697 }
2698
2699 // Add a (token, address) pair to the table of IL blobs for reflection/dynamics
2700 // Arguments:
2701 //     Input:
2702 //         token        method token
2703 //         blobAddress  address of the start of the IL blob address, including the header
2704 //         fTemporaryOverride
2705 //                      is this a permanent override that should go in the
2706 //                      DynamicILBlobTable, or a temporary one?
2707 //     Output: not explicit, but if the pair was not already in the table it will be added.
2708 //             Does not add duplicate tokens to the table. 
2709
2710 void Module::SetDynamicIL(mdToken token, TADDR blobAddress, BOOL fTemporaryOverride)
2711 {
2712     DynamicILBlobEntry entry = {mdToken(token), TADDR(blobAddress)};
2713
2714     // Lazily allocate a Crst to serialize update access to the info structure.
2715     // Carefully synchronize to ensure we don't leak a Crst in race conditions.
2716     if (m_debuggerSpecificData.m_pDynamicILCrst == NULL)
2717     {
2718         InitializeDynamicILCrst();
2719     }
2720
2721     CrstHolder ch(m_debuggerSpecificData.m_pDynamicILCrst);
2722    
2723     // Figure out which table to fill in
2724     PTR_DynamicILBlobTable &table(fTemporaryOverride ? m_debuggerSpecificData.m_pTemporaryILBlobTable 
2725                                                      : m_debuggerSpecificData.m_pDynamicILBlobTable);
2726
2727     // Lazily allocate the hash table.
2728     if (table == NULL)
2729     {
2730         table = PTR_DynamicILBlobTable(new DynamicILBlobTable);
2731     }
2732     table->AddOrReplace(entry);
2733 }
2734
2735 #endif // !DACCESS_COMPILE
2736
2737 // Get the stored address of the IL blob for reflection/dynamics
2738 // Arguments:
2739 //     Input:
2740 //         token        method token
2741 //         fAllowTemporary also check the temporary overrides
2742 // Return Value: starting (target) address of the IL blob corresponding to the input token
2743
2744 TADDR Module::GetDynamicIL(mdToken token, BOOL fAllowTemporary)
2745 {
2746     SUPPORTS_DAC;
2747
2748 #ifndef DACCESS_COMPILE
2749     // The Crst to serialize update access to the info structure is lazily allocated.
2750     // If it hasn't been allocated yet, then we don't have any IL blobs (temporary or otherwise)
2751     if (m_debuggerSpecificData.m_pDynamicILCrst == NULL)
2752     {
2753         return TADDR(NULL);
2754     }
2755
2756     CrstHolder ch(m_debuggerSpecificData.m_pDynamicILCrst);
2757 #endif
2758  
2759     // Both hash tables are lazily allocated, so if they're NULL
2760     // then we have no IL blobs
2761
2762     if (fAllowTemporary && m_debuggerSpecificData.m_pTemporaryILBlobTable != NULL)
2763     {
2764         DynamicILBlobEntry entry = m_debuggerSpecificData.m_pTemporaryILBlobTable->Lookup(token);
2765
2766         // Only return a value if the lookup succeeded
2767         if (!DynamicILBlobTraits::IsNull(entry))
2768         {
2769             return entry.m_il;
2770         }
2771     }
2772  
2773     if (m_debuggerSpecificData.m_pDynamicILBlobTable == NULL)
2774     {
2775         return TADDR(NULL);
2776     }
2777
2778     DynamicILBlobEntry entry = m_debuggerSpecificData.m_pDynamicILBlobTable->Lookup(token);
2779     // If the lookup fails, it returns the 'NULL' entry
2780     // The 'NULL' entry has m_il set to NULL, so either way we're safe
2781     return entry.m_il;
2782 }
2783
2784 #if !defined(DACCESS_COMPILE)
2785 //---------------------------------------------------------------------------------------
2786 //
2787 // Add instrumented IL offset mapping for the specified method.
2788 //
2789 // Arguments:
2790 //    token   - the MethodDef token of the method in question
2791 //    mapping - the mapping information between original IL offsets and instrumented IL offsets
2792 //
2793 // Notes:
2794 //    * Once added, the mapping stays valid until the Module containing the method is destructed.
2795 //    * The profiler may potentially update the mapping more than once.
2796 //
2797
2798 void Module::SetInstrumentedILOffsetMapping(mdMethodDef token, InstrumentedILOffsetMapping mapping)
2799 {
2800     ILOffsetMappingEntry entry(token, mapping);
2801
2802     // Lazily allocate a Crst to serialize update access to the hash table.
2803     // Carefully synchronize to ensure we don't leak a Crst in race conditions.
2804     if (m_debuggerSpecificData.m_pDynamicILCrst == NULL)
2805     {
2806         InitializeDynamicILCrst();
2807     }
2808
2809     CrstHolder ch(m_debuggerSpecificData.m_pDynamicILCrst);
2810    
2811     // Lazily allocate the hash table.
2812     if (m_debuggerSpecificData.m_pILOffsetMappingTable == NULL)
2813     {
2814         m_debuggerSpecificData.m_pILOffsetMappingTable = PTR_ILOffsetMappingTable(new ILOffsetMappingTable);
2815     }
2816
2817     ILOffsetMappingEntry currentEntry = m_debuggerSpecificData.m_pILOffsetMappingTable->Lookup(ILOffsetMappingTraits::GetKey(entry));
2818     if (!ILOffsetMappingTraits::IsNull(currentEntry))
2819         currentEntry.m_mapping.Clear();
2820
2821     m_debuggerSpecificData.m_pILOffsetMappingTable->AddOrReplace(entry);
2822 }
2823 #endif // DACCESS_COMPILE
2824
2825 //---------------------------------------------------------------------------------------
2826 //
2827 // Retrieve the instrumented IL offset mapping for the specified method.
2828 //
2829 // Arguments:
2830 //    token   - the MethodDef token of the method in question
2831 //
2832 // Return Value:
2833 //    Return the mapping information between original IL offsets and instrumented IL offsets.
2834 //    Check InstrumentedILOffsetMapping::IsNull() to see if any mapping is available.
2835 //
2836 // Notes:
2837 //    * Once added, the mapping stays valid until the Module containing the method is destructed.
2838 //    * The profiler may potentially update the mapping more than once.
2839 //
2840
2841 InstrumentedILOffsetMapping Module::GetInstrumentedILOffsetMapping(mdMethodDef token)
2842 {
2843     CONTRACTL
2844     {
2845         THROWS;
2846         GC_NOTRIGGER;
2847         MODE_ANY;
2848         SUPPORTS_DAC;
2849     }
2850     CONTRACTL_END;
2851
2852     // Lazily allocate a Crst to serialize update access to the hash table.
2853     // If the Crst is NULL, then we couldn't possibly have added any mapping yet, so just return NULL.
2854     if (m_debuggerSpecificData.m_pDynamicILCrst == NULL)
2855     {
2856         InstrumentedILOffsetMapping emptyMapping;
2857         return emptyMapping;
2858     }
2859
2860     CrstHolder ch(m_debuggerSpecificData.m_pDynamicILCrst);
2861  
2862     // If the hash table hasn't been created, then we couldn't possibly have added any mapping yet, 
2863     // so just return NULL.
2864     if (m_debuggerSpecificData.m_pILOffsetMappingTable == NULL)
2865     {
2866         InstrumentedILOffsetMapping emptyMapping;
2867         return emptyMapping;
2868     }
2869
2870     ILOffsetMappingEntry entry = m_debuggerSpecificData.m_pILOffsetMappingTable->Lookup(token);
2871     return entry.m_mapping;
2872 }
2873
2874 #undef DECODE_TYPEID
2875 #undef ENCODE_TYPEID
2876 #undef IS_ENCODED_TYPEID
2877
2878
2879
2880 #ifndef DACCESS_COMPILE 
2881
2882
2883 BOOL Module::IsNoStringInterning()
2884 {
2885     CONTRACTL
2886     {
2887         THROWS;
2888         GC_TRIGGERS;
2889     }
2890     CONTRACTL_END
2891
2892     if (!(m_dwPersistedFlags & COMPUTED_STRING_INTERNING))
2893     {
2894         // The flags should be precomputed in native images
2895         _ASSERTE(!HasNativeImage());
2896
2897         // Default is string interning
2898         BOOL fNoStringInterning = FALSE;
2899
2900         HRESULT hr;
2901         
2902         // This flag applies to assembly, but it is stored on module so it can be cached in ngen image
2903         // Thus, we should ever need it for manifest module only.
2904         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
2905         _ASSERTE(mdImport);
2906         
2907         mdToken token;
2908         IfFailThrow(mdImport->GetAssemblyFromScope(&token));
2909         
2910         const BYTE *pVal;
2911         ULONG       cbVal;
2912         
2913         hr = mdImport->GetCustomAttributeByName(token,
2914                         COMPILATIONRELAXATIONS_TYPE,
2915                         (const void**)&pVal, &cbVal);
2916         
2917         // Parse the attribute
2918         if (hr == S_OK)
2919         {
2920             CustomAttributeParser cap(pVal, cbVal);
2921             IfFailThrow(cap.SkipProlog());
2922
2923             // Get Flags
2924             UINT32 flags;
2925             IfFailThrow(cap.GetU4(&flags));
2926
2927             if (flags & CompilationRelaxations_NoStringInterning)
2928             {
2929                 fNoStringInterning = TRUE;
2930             }
2931         }
2932
2933 #ifdef _DEBUG
2934         static ConfigDWORD g_NoStringInterning;
2935         DWORD dwOverride = g_NoStringInterning.val(CLRConfig::INTERNAL_NoStringInterning);
2936
2937         if (dwOverride == 0)
2938         {
2939             // Disabled
2940             fNoStringInterning = FALSE;
2941         }
2942         else if (dwOverride == 2)
2943         {
2944             // Always true (testing)
2945             fNoStringInterning = TRUE;
2946         }
2947 #endif // _DEBUG
2948
2949         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_STRING_INTERNING |
2950             (fNoStringInterning ? NO_STRING_INTERNING : 0));
2951     }
2952
2953     return !!(m_dwPersistedFlags & NO_STRING_INTERNING);
2954 }
2955
2956 BOOL Module::GetNeutralResourcesLanguage(LPCUTF8 * cultureName, ULONG * cultureNameLength, INT16 * fallbackLocation, BOOL cacheAttribute)
2957 {
2958     STANDARD_VM_CONTRACT;
2959
2960     BOOL retVal = FALSE;
2961     if (!(m_dwPersistedFlags & NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED))
2962     {
2963         const BYTE *pVal = NULL;
2964         ULONG cbVal = 0;
2965
2966         // This flag applies to assembly, but it is stored on module so it can be cached in ngen image
2967         // Thus, we should ever need it for manifest module only.
2968         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
2969         _ASSERTE(mdImport);
2970
2971         mdToken token;
2972         IfFailThrow(mdImport->GetAssemblyFromScope(&token));
2973
2974         // Check for the existance of the attribute.
2975         HRESULT hr = mdImport->GetCustomAttributeByName(token,"System.Resources.NeutralResourcesLanguageAttribute",(const void **)&pVal, &cbVal);
2976         if (hr == S_OK) {
2977
2978             // we should not have a native image (it would have been cached at ngen time)
2979             _ASSERTE(!HasNativeImage());
2980
2981             CustomAttributeParser cap(pVal, cbVal);
2982             IfFailThrow(cap.SkipProlog());
2983             IfFailThrow(cap.GetString(cultureName, cultureNameLength));
2984             IfFailThrow(cap.GetI2(fallbackLocation));
2985             // Should only be true on Module.Save(). Update flag to show we have the attribute cached
2986             if (cacheAttribute)
2987                 FastInterlockOr(&m_dwPersistedFlags, NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED);
2988
2989             retVal = TRUE;
2990         }
2991     }
2992     else 
2993     {
2994         *cultureName = m_pszCultureName;
2995         *cultureNameLength = m_CultureNameLength;
2996         *fallbackLocation = m_FallbackLocation;
2997         retVal = TRUE;
2998
2999 #ifdef _DEBUG
3000         // confirm that the NGENed attribute is correct
3001         LPCUTF8 pszCultureNameCheck = NULL;
3002         ULONG cultureNameLengthCheck = 0;
3003         INT16 fallbackLocationCheck = 0;
3004         const BYTE *pVal = NULL;
3005         ULONG cbVal = 0;
3006
3007         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
3008         _ASSERTE(mdImport);
3009         mdToken token;
3010         IfFailThrow(mdImport->GetAssemblyFromScope(&token));
3011
3012         // Confirm that the attribute exists, and has the save value as when we ngen'd it
3013         HRESULT hr = mdImport->GetCustomAttributeByName(token,"System.Resources.NeutralResourcesLanguageAttribute",(const void **)&pVal, &cbVal);
3014         _ASSERTE(hr == S_OK);
3015         CustomAttributeParser cap(pVal, cbVal);
3016         IfFailThrow(cap.SkipProlog());
3017         IfFailThrow(cap.GetString(&pszCultureNameCheck, &cultureNameLengthCheck));
3018         IfFailThrow(cap.GetI2(&fallbackLocationCheck));
3019         _ASSERTE(cultureNameLengthCheck == m_CultureNameLength);
3020         _ASSERTE(fallbackLocationCheck == m_FallbackLocation);
3021         _ASSERTE(strncmp(pszCultureNameCheck,m_pszCultureName,m_CultureNameLength) == 0);
3022 #endif // _DEBUG
3023     }
3024
3025     return retVal;
3026 }
3027
3028
3029 BOOL Module::HasDefaultDllImportSearchPathsAttribute()
3030 {
3031     CONTRACTL
3032     {
3033         THROWS;
3034         GC_NOTRIGGER;
3035         MODE_ANY;
3036     }
3037     CONTRACTL_END;
3038
3039     if(IsDefaultDllImportSearchPathsAttributeCached())
3040     {
3041         return (m_dwPersistedFlags & DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS) != 0 ;
3042     }
3043     IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
3044
3045     BOOL attributeIsFound = FALSE;
3046     attributeIsFound = GetDefaultDllImportSearchPathsAttributeValue(mdImport, TokenFromRid(1, mdtAssembly),&m_DefaultDllImportSearchPathsAttributeValue);
3047     if(attributeIsFound)
3048     {
3049         FastInterlockOr(&m_dwPersistedFlags, DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED | DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS);
3050     }
3051     else
3052     {
3053         FastInterlockOr(&m_dwPersistedFlags, DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED);
3054     }
3055
3056     return (m_dwPersistedFlags & DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS) != 0 ;
3057 }
3058
3059 // Returns a BOOL to indicate if we have computed whether compiler has instructed us to
3060 // wrap the non-CLS compliant exceptions or not.
3061 BOOL Module::IsRuntimeWrapExceptionsStatusComputed()
3062 {
3063     LIMITED_METHOD_CONTRACT;
3064
3065     return (m_dwPersistedFlags & COMPUTED_WRAP_EXCEPTIONS);
3066 }
3067
3068 BOOL Module::IsRuntimeWrapExceptions()
3069 {
3070     CONTRACTL
3071     {
3072         THROWS;
3073         if (IsRuntimeWrapExceptionsStatusComputed()) GC_NOTRIGGER; else GC_TRIGGERS;
3074         MODE_ANY;
3075     }
3076     CONTRACTL_END
3077
3078     if (!(IsRuntimeWrapExceptionsStatusComputed()))
3079     {
3080         // The flags should be precomputed in native images
3081         _ASSERTE(!HasNativeImage());
3082         
3083         HRESULT hr;
3084         BOOL fRuntimeWrapExceptions = FALSE;
3085         
3086         // This flag applies to assembly, but it is stored on module so it can be cached in ngen image
3087         // Thus, we should ever need it for manifest module only.
3088         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
3089         
3090         mdToken token;
3091         IfFailGo(mdImport->GetAssemblyFromScope(&token));
3092         
3093         const BYTE *pVal;
3094         ULONG       cbVal;
3095         
3096         hr = mdImport->GetCustomAttributeByName(token,
3097                         RUNTIMECOMPATIBILITY_TYPE,
3098                         (const void**)&pVal, &cbVal);
3099
3100         // Parse the attribute
3101         if (hr == S_OK)
3102         {
3103             CustomAttributeParser ca(pVal, cbVal);
3104             CaNamedArg namedArgs[1] = {{0}};
3105             
3106             // First, the void constructor:
3107             IfFailGo(ParseKnownCaArgs(ca, NULL, 0));
3108             
3109             // Then, find the named argument
3110             namedArgs[0].InitBoolField("WrapNonExceptionThrows");
3111             
3112             IfFailGo(ParseKnownCaNamedArgs(ca, namedArgs, lengthof(namedArgs)));
3113             
3114             if (namedArgs[0].val.boolean)
3115                 fRuntimeWrapExceptions = TRUE;
3116         }
3117 ErrExit:
3118         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_WRAP_EXCEPTIONS |
3119             (fRuntimeWrapExceptions ? WRAP_EXCEPTIONS : 0));
3120     }
3121     
3122     return !!(m_dwPersistedFlags & WRAP_EXCEPTIONS);
3123 }
3124
3125 BOOL Module::IsPreV4Assembly()
3126 {
3127     CONTRACTL
3128     {
3129         THROWS;
3130         GC_NOTRIGGER;
3131         SO_TOLERANT;
3132     }
3133     CONTRACTL_END
3134
3135     if (!(m_dwPersistedFlags & COMPUTED_IS_PRE_V4_ASSEMBLY))
3136     {
3137         // The flags should be precomputed in native images
3138         _ASSERTE(!HasNativeImage());
3139         
3140         IMDInternalImport *pImport = GetAssembly()->GetManifestImport();
3141         _ASSERTE(pImport);
3142         
3143         BOOL fIsPreV4Assembly = FALSE;
3144         LPCSTR szVersion = NULL;
3145         if (SUCCEEDED(pImport->GetVersionString(&szVersion)))
3146         {
3147             if (szVersion != NULL && strlen(szVersion) > 2)
3148             {
3149                 fIsPreV4Assembly = (szVersion[0] == 'v' || szVersion[0] == 'V') &&
3150                                    (szVersion[1] == '1' || szVersion[1] == '2');
3151             }
3152         }
3153
3154         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_IS_PRE_V4_ASSEMBLY |
3155             (fIsPreV4Assembly ? IS_PRE_V4_ASSEMBLY : 0));
3156     }
3157
3158     return !!(m_dwPersistedFlags & IS_PRE_V4_ASSEMBLY);
3159 }
3160
3161 #ifdef FEATURE_CER
3162 DWORD Module::GetReliabilityContract()
3163 {
3164     CONTRACTL
3165     {
3166         NOTHROW;
3167         GC_NOTRIGGER;
3168         MODE_ANY;
3169     }
3170     CONTRACTL_END
3171
3172     if (!(m_dwPersistedFlags & COMPUTED_RELIABILITY_CONTRACT))
3173     {
3174         // The flags should be precomputed in native images
3175         _ASSERTE(!HasNativeImage());
3176
3177         // This flag applies to assembly, but it is stored on module so it can be cached in ngen image
3178         // Thus, we should ever need it for manifest module only.
3179         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
3180
3181         m_dwReliabilityContract = ::GetReliabilityContract(mdImport, TokenFromRid(1, mdtAssembly));
3182
3183         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_RELIABILITY_CONTRACT);
3184     }
3185
3186     return m_dwReliabilityContract;
3187 }
3188 #endif // FEATURE_CER
3189
3190 ArrayDPTR(FixupPointer<PTR_MethodTable>) ModuleCtorInfo::GetGCStaticMTs(DWORD index)
3191 {
3192     LIMITED_METHOD_CONTRACT;
3193
3194     if (index < numHotGCStaticsMTs)
3195     {
3196         _ASSERTE(ppHotGCStaticsMTs != NULL);
3197
3198         return ppHotGCStaticsMTs + index;
3199     }
3200     else
3201     {
3202         _ASSERTE(ppColdGCStaticsMTs != NULL);
3203
3204         // shift the start of the cold table because all cold offsets are also shifted
3205         return ppColdGCStaticsMTs + (index - numHotGCStaticsMTs);
3206     }
3207 }
3208
3209 DWORD Module::AllocateDynamicEntry(MethodTable *pMT)
3210 {
3211     CONTRACTL
3212     {
3213         THROWS;
3214         GC_TRIGGERS;
3215         PRECONDITION(pMT->GetModuleForStatics() == this);
3216         PRECONDITION(pMT->IsDynamicStatics());
3217         PRECONDITION(!pMT->ContainsGenericVariables());
3218     }
3219     CONTRACTL_END;
3220
3221     DWORD newId = FastInterlockExchangeAdd((LONG*)&m_cDynamicEntries, 1);
3222
3223     if (newId >= m_maxDynamicEntries)
3224     {
3225         CrstHolder ch(&m_Crst);
3226
3227         if (newId >= m_maxDynamicEntries)
3228         {
3229             SIZE_T maxDynamicEntries = max(16, m_maxDynamicEntries);
3230             while (maxDynamicEntries <= newId)
3231             {
3232                 maxDynamicEntries *= 2;
3233             }
3234
3235             DynamicStaticsInfo* pNewDynamicStaticsInfo = (DynamicStaticsInfo*)
3236                 (void*)GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicStaticsInfo)) * S_SIZE_T(maxDynamicEntries));
3237
3238             if (m_pDynamicStaticsInfo)
3239                 memcpy(pNewDynamicStaticsInfo, m_pDynamicStaticsInfo, sizeof(DynamicStaticsInfo) * m_maxDynamicEntries);
3240
3241             m_pDynamicStaticsInfo = pNewDynamicStaticsInfo;
3242             m_maxDynamicEntries = maxDynamicEntries;
3243         }
3244     }
3245
3246     EnsureWritablePages(&(m_pDynamicStaticsInfo[newId]))->pEnclosingMT = pMT;
3247
3248     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Assigned dynamic ID %d to %s\n", newId, pMT->GetDebugClassName()));
3249
3250     return newId;
3251 }
3252
3253 void Module::FreeModuleIndex()
3254 {
3255     CONTRACTL
3256     {
3257         NOTHROW;
3258         GC_NOTRIGGER;
3259         MODE_ANY;
3260     }
3261     CONTRACTL_END;
3262     if (GetAssembly()->IsDomainNeutral())
3263     {
3264         // We do not recycle ModuleIndexes used by domain neutral Modules.
3265     }
3266     else 
3267     {
3268         if (m_ModuleID != NULL)
3269         {
3270             // Module's m_ModuleID should not contain the ID, it should 
3271             // contain a pointer to the DLM
3272             _ASSERTE(!Module::IsEncodedModuleIndex((SIZE_T)m_ModuleID));
3273             _ASSERTE(m_ModuleIndex == m_ModuleID->GetModuleIndex());
3274
3275             // Get the ModuleIndex from the DLM and free it
3276             Module::FreeModuleIndex(m_ModuleIndex);
3277         }
3278         else
3279         {
3280             // This was an empty, short-lived Module object that
3281             // was never assigned a ModuleIndex...
3282         }
3283     }
3284 }
3285
3286
3287
3288
3289 ModuleIndex Module::AllocateModuleIndex()
3290 {
3291     DWORD val;
3292     g_pModuleIndexDispenser->NewId(NULL, val);
3293
3294     // For various reasons, the IDs issued by the IdDispenser start at 1.
3295     // Domain neutral module IDs have historically started at 0, and we
3296     // have always assigned ID 0 to mscorlib. Thus, to make it so that
3297     // domain neutral module IDs start at 0, we will subtract 1 from the
3298     // ID that we got back from the ID dispenser.
3299     ModuleIndex index((SIZE_T)(val-1));
3300
3301     return index;
3302 }
3303
3304 void Module::FreeModuleIndex(ModuleIndex index)
3305 {
3306     WRAPPER_NO_CONTRACT;
3307     // We subtracted 1 after we allocated this ID, so we need to
3308     // add 1 before we free it.
3309     DWORD val = index.m_dwIndex + 1;
3310
3311     g_pModuleIndexDispenser->DisposeId(val);
3312 }
3313
3314
3315 void Module::AllocateRegularStaticHandles(AppDomain* pDomain)
3316 {
3317     CONTRACTL
3318     {
3319         THROWS;
3320         GC_TRIGGERS;
3321     }
3322     CONTRACTL_END;
3323
3324 #ifndef CROSSGEN_COMPILE
3325     if (NingenEnabled())
3326         return;
3327
3328     // Allocate the handles we will need. Note that AllocateStaticFieldObjRefPtrs will only
3329     // allocate if pModuleData->GetGCStaticsBasePointerAddress(pMT) != 0, avoiding creating
3330     // handles more than once for a given MT or module
3331
3332     DomainLocalModule *pModuleData = GetDomainLocalModule(pDomain);
3333
3334     _ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointerAddress() != NULL);
3335     if (this->m_dwMaxGCRegularStaticHandles > 0)
3336     {
3337         // If we're setting up a non-default domain, we want the allocation to look like it's
3338         // coming from the created domain.
3339
3340         // REVISIT_TODO: The comparison "pDomain != GetDomain()" will always be true for domain-neutral
3341         // modules, since GetDomain() will return the SharedDomain, which is NOT an AppDomain.
3342         // Was this intended? If so, there should be a clarifying comment. If not, then we should
3343         // probably do "pDomain != GetAppDomain()" instead.
3344
3345         if (pDomain != GetDomain() &&
3346             pDomain != SystemDomain::System()->DefaultDomain() &&
3347             IsSystem())
3348         {
3349             pDomain->AllocateStaticFieldObjRefPtrsCrossDomain(this->m_dwMaxGCRegularStaticHandles,
3350                                                pModuleData->GetPrecomputedGCStaticsBasePointerAddress());
3351         }
3352         else
3353         {
3354             pDomain->AllocateStaticFieldObjRefPtrs(this->m_dwMaxGCRegularStaticHandles,
3355                                                pModuleData->GetPrecomputedGCStaticsBasePointerAddress());
3356         }
3357
3358         // We should throw if we fail to allocate and never hit this assert
3359         _ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointer() != NULL);
3360     }
3361 #endif // CROSSGEN_COMPILE
3362 }
3363
3364 BOOL Module::IsStaticStoragePrepared(mdTypeDef tkType)
3365 {
3366     LIMITED_METHOD_CONTRACT;
3367
3368     // Right now the design is that we do one static allocation pass during NGEN,
3369     // and a 2nd pass for it at module init time for modules that weren't NGENed or the NGEN
3370     // pass was unsucessful. If we are loading types after that then we must use dynamic
3371     // static storage. These dynamic statics require an additional indirection so they
3372     // don't perform quite as well. 
3373     //
3374     // This check was created for the scenario where a profiler adds additional types
3375     // however it seems likely this check would also accurately handle other dynamic
3376     // scenarios such as ref.emit and EnC as long as they are adding new types and
3377     // not new statics to existing types.
3378     _ASSERTE(TypeFromToken(tkType) == mdtTypeDef);
3379     return m_maxTypeRidStaticsAllocated >= RidFromToken(tkType);
3380 }
3381
3382 void Module::AllocateStatics(AllocMemTracker *pamTracker)
3383 {
3384     STANDARD_VM_CONTRACT;
3385
3386     if (IsResource())
3387     {
3388         m_dwRegularStaticsBlockSize = DomainLocalModule::OffsetOfDataBlob();
3389         m_dwThreadStaticsBlockSize = ThreadLocalModule::OffsetOfDataBlob();
3390
3391         // If it has no code, we don't have to allocate anything
3392         LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Resource module %s. No statics neeeded\n", GetSimpleName()));
3393         _ASSERTE(m_maxTypeRidStaticsAllocated == 0);
3394         return;
3395     }
3396 #ifdef FEATURE_PREJIT
3397     if (m_pRegularStaticOffsets == (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED)
3398     {
3399         _ASSERTE(HasNativeImage());
3400
3401         // This is an ngen image and all the classes were loaded at ngen time, so we're done.
3402         LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: 'Complete' Native image found, no statics parsing needed for module %s.\n", GetSimpleName()));
3403         // typeDefs rids 0 and 1 aren't included in the count, thus X typeDefs means rid X+1 is valid
3404         _ASSERTE(m_maxTypeRidStaticsAllocated == GetMDImport()->GetCountWithTokenKind(mdtTypeDef) + 1);
3405         return;
3406     }
3407 #endif
3408     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Allocating statics for module %s\n", GetSimpleName()));
3409
3410     // 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
3411     // for non gc types)
3412     BuildStaticsOffsets(pamTracker);
3413 }
3414
3415 // This method will report GC static refs of the module. It doesn't have to be complete (ie, it's 
3416 // currently used to opportunistically get more concurrency in the marking of statics), so it currently
3417 // ignores any statics that are not preallocated (ie: won't report statics from IsDynamicStatics() MT)
3418 // The reason this function is in Module and not in DomainFile (together with DomainLocalModule is because
3419 // for shared modules we need a very fast way of getting to the DomainLocalModule. For that we use
3420 // a table in DomainLocalBlock that's indexed with a module ID
3421 //
3422 // This method is a secondary way for the GC to find statics, and it is only used when we are on
3423 // a multiproc machine and we are using the ServerHeap. The primary way used by the GC to find 
3424 // statics is through the handle table. Module::AllocateRegularStaticHandles() allocates a GC handle
3425 // from the handle table, and the GC will trace this handle and find the statics.
3426
3427 void Module::EnumRegularStaticGCRefs(AppDomain* pAppDomain, promote_func* fn, ScanContext* sc)
3428 {
3429     CONTRACT_VOID
3430     {
3431         NOTHROW;
3432         GC_NOTRIGGER;
3433     }
3434     CONTRACT_END;
3435
3436     _ASSERTE(GCHeapUtilities::IsGCInProgress() && 
3437          GCHeapUtilities::IsServerHeap() && 
3438          IsGCSpecialThread());
3439
3440
3441     DomainLocalModule *pModuleData = GetDomainLocalModule(pAppDomain);
3442     DWORD dwHandles                = m_dwMaxGCRegularStaticHandles;
3443
3444     if (IsResource())
3445     {
3446         RETURN;
3447     }
3448
3449     LOG((LF_GC, LL_INFO100, "Scanning statics for module %s\n", GetSimpleName()));
3450
3451     OBJECTREF* ppObjectRefs       = pModuleData->GetPrecomputedGCStaticsBasePointer();
3452     for (DWORD i = 0 ; i < dwHandles ; i++)
3453     {
3454         // Handles are allocated in SetDomainFile (except for bootstrapped mscorlib). In any
3455         // case, we shouldnt get called if the module hasn't had it's handles allocated (as we
3456         // only get here if IsActive() is true, which only happens after SetDomainFile(), which
3457         // is were we allocate handles.
3458         _ASSERTE(ppObjectRefs);
3459         fn((Object **)(ppObjectRefs+i), sc, 0);
3460     }
3461
3462     LOG((LF_GC, LL_INFO100, "Done scanning statics for module %s\n", GetSimpleName()));
3463
3464     RETURN;
3465 }
3466
3467 void Module::SetDomainFile(DomainFile *pDomainFile)
3468 {
3469     CONTRACTL
3470     {
3471         INSTANCE_CHECK;
3472         PRECONDITION(CheckPointer(pDomainFile));
3473         PRECONDITION(IsManifest() == pDomainFile->IsAssembly());
3474         THROWS;
3475         GC_TRIGGERS;
3476         MODE_ANY;
3477     }
3478     CONTRACTL_END;
3479
3480     DomainLocalModule* pModuleData = 0;
3481
3482     // Do we need to allocate memory for the non GC statics?
3483     if ((GetAssembly()->IsDomainNeutral() && !IsSingleAppDomain())|| m_ModuleID == NULL)
3484     {
3485         // Allocate memory for the module statics.
3486         LoaderAllocator *pLoaderAllocator = NULL;
3487         if (GetAssembly()->IsCollectible())
3488         {
3489             pLoaderAllocator = GetAssembly()->GetLoaderAllocator();
3490         }
3491         else
3492         {
3493             pLoaderAllocator = pDomainFile->GetAppDomain()->GetLoaderAllocator();
3494         }
3495
3496         SIZE_T size = GetDomainLocalModuleSize();
3497
3498         LOG((LF_CLASSLOADER, LL_INFO10, "STATICS: Allocating %i bytes for precomputed statics in module %S in LoaderAllocator %p\n",
3499             size, this->GetDebugName(), pLoaderAllocator));
3500
3501         // We guarantee alignment for 64-bit regular statics on 32-bit platforms even without FEATURE_64BIT_ALIGNMENT for performance reasons.
3502
3503         _ASSERTE(size >= DomainLocalModule::OffsetOfDataBlob());
3504
3505         pModuleData = (DomainLocalModule*)(void*)
3506             pLoaderAllocator->GetHighFrequencyHeap()->AllocAlignedMem(
3507                 size, MAX_PRIMITIVE_FIELD_SIZE);
3508
3509         // Note: Memory allocated on loader heap is zero filled
3510         // memset(pModuleData, 0, size);
3511
3512         // Verify that the space is really zero initialized
3513         _ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointer() == NULL);
3514
3515         // Make sure that the newly allocated DomainLocalModule gets 
3516         // a copy of the domain-neutral module ID. 
3517         if (GetAssembly()->IsDomainNeutral() && !IsSingleAppDomain())
3518         {
3519             // If the module was loaded as domain-neutral, we can find the ID by 
3520             // casting 'm_ModuleID'.
3521             
3522             _ASSERTE(Module::IDToIndex((SIZE_T)m_ModuleID) == this->m_ModuleIndex);
3523             pModuleData->m_ModuleIndex = Module::IDToIndex((SIZE_T)m_ModuleID);
3524
3525             // Eventually I want to just do this instead...
3526             //pModuleData->m_ModuleIndex = this->m_ModuleIndex;
3527         }
3528         else
3529         {
3530             // If the module was loaded as domain-specific, then we need to assign
3531             // this module a domain-neutral module ID.
3532             pModuleData->m_ModuleIndex = Module::AllocateModuleIndex();
3533             m_ModuleIndex = pModuleData->m_ModuleIndex;
3534         }
3535     }
3536     else
3537     {
3538         pModuleData = this->m_ModuleID;
3539         LOG((LF_CLASSLOADER, LL_INFO10, "STATICS: Allocation not needed for ngened non shared module %s in Appdomain %08x\n"));
3540     }
3541
3542     if (GetAssembly()->IsDomainNeutral() && !IsSingleAppDomain())
3543     {
3544         DomainLocalBlock *pLocalBlock;
3545         {
3546             pLocalBlock = pDomainFile->GetAppDomain()->GetDomainLocalBlock();
3547             pLocalBlock->SetModuleSlot(GetModuleIndex(), pModuleData);
3548         }
3549
3550         pLocalBlock->SetDomainFile(GetModuleIndex(), pDomainFile);
3551     }
3552     else
3553     {
3554         // Non shared case, module points directly to the statics. In ngen case
3555         // m_pDomainModule is already set for the non shared case
3556         if (m_ModuleID == NULL)
3557         {
3558             m_ModuleID = pModuleData;
3559         }
3560
3561         m_ModuleID->SetDomainFile(pDomainFile);
3562     }
3563
3564     // Allocate static handles now.
3565     // NOTE: Bootstrapping issue with mscorlib - we will manually allocate later
3566     if (g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] != NULL)
3567         AllocateRegularStaticHandles(pDomainFile->GetAppDomain());
3568 }
3569
3570 #ifndef CROSSGEN_COMPILE
3571 OBJECTREF Module::GetExposedObject()
3572 {
3573     CONTRACT(OBJECTREF)
3574     {
3575         INSTANCE_CHECK;
3576         POSTCONDITION(RETVAL != NULL);
3577         THROWS;
3578         GC_TRIGGERS;
3579         MODE_COOPERATIVE;
3580     }
3581     CONTRACT_END;
3582
3583     RETURN GetDomainFile()->GetExposedModuleObject();
3584 }
3585 #endif // CROSSGEN_COMPILE
3586
3587 //
3588 // AllocateMap allocates the RID maps based on the size of the current
3589 // metadata (if any)
3590 //
3591
3592 void Module::AllocateMaps()
3593 {
3594     CONTRACTL
3595     {
3596         INSTANCE_CHECK;
3597         THROWS;
3598         GC_NOTRIGGER;
3599         MODE_ANY;
3600     }
3601     CONTRACTL_END;
3602
3603     enum
3604     {
3605         TYPEDEF_MAP_INITIAL_SIZE = 5,
3606         TYPEREF_MAP_INITIAL_SIZE = 5,
3607         MEMBERDEF_MAP_INITIAL_SIZE = 10,
3608         GENERICPARAM_MAP_INITIAL_SIZE = 5,
3609         GENERICTYPEDEF_MAP_INITIAL_SIZE = 5,
3610         FILEREFERENCES_MAP_INITIAL_SIZE = 5,
3611         ASSEMBLYREFERENCES_MAP_INITIAL_SIZE = 5,
3612     };
3613
3614     PTR_TADDR pTable = NULL;
3615
3616     if (IsResource())
3617         return;
3618
3619     if (IsReflection())
3620     {
3621         // For dynamic modules, it is essential that we at least have a TypeDefToMethodTable
3622         // map with an initial block.  Otherwise, all the iterators will abort on an
3623         // initial empty table and we will e.g. corrupt the backpatching chains during
3624         // an appdomain unload.
3625         m_TypeDefToMethodTableMap.dwCount = TYPEDEF_MAP_INITIAL_SIZE;
3626
3627         // The above is essential.  The following ones are precautionary.
3628         m_TypeRefToMethodTableMap.dwCount = TYPEREF_MAP_INITIAL_SIZE;
3629         m_MethodDefToDescMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE;
3630         m_FieldDefToDescMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE;
3631         m_GenericParamToDescMap.dwCount = GENERICPARAM_MAP_INITIAL_SIZE;
3632         m_GenericTypeDefToCanonMethodTableMap.dwCount = TYPEDEF_MAP_INITIAL_SIZE;
3633         m_FileReferencesMap.dwCount = FILEREFERENCES_MAP_INITIAL_SIZE;
3634         m_ManifestModuleReferencesMap.dwCount = ASSEMBLYREFERENCES_MAP_INITIAL_SIZE;
3635         m_MethodDefToPropertyInfoMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE;
3636     }
3637     else
3638     {
3639         IMDInternalImport * pImport = GetMDImport();
3640
3641         // Get # TypeDefs (add 1 for COR_GLOBAL_PARENT_TOKEN)
3642         m_TypeDefToMethodTableMap.dwCount = pImport->GetCountWithTokenKind(mdtTypeDef)+2;
3643
3644         // Get # TypeRefs
3645         m_TypeRefToMethodTableMap.dwCount = pImport->GetCountWithTokenKind(mdtTypeRef)+1;
3646
3647         // Get # MethodDefs
3648         m_MethodDefToDescMap.dwCount = pImport->GetCountWithTokenKind(mdtMethodDef)+1;
3649
3650         // Get # FieldDefs
3651         m_FieldDefToDescMap.dwCount = pImport->GetCountWithTokenKind(mdtFieldDef)+1;
3652
3653         // Get # GenericParams
3654         m_GenericParamToDescMap.dwCount = pImport->GetCountWithTokenKind(mdtGenericParam)+1;
3655
3656         // Get the number of FileReferences in the map
3657         m_FileReferencesMap.dwCount = pImport->GetCountWithTokenKind(mdtFile)+1;
3658
3659         // Get the number of AssemblyReferences in the map
3660         m_ManifestModuleReferencesMap.dwCount = pImport->GetCountWithTokenKind(mdtAssemblyRef)+1;
3661
3662         // These maps are only added to during NGen, so for other scenarios leave them empty
3663         if (IsCompilationProcess())
3664         {
3665             m_GenericTypeDefToCanonMethodTableMap.dwCount = m_TypeDefToMethodTableMap.dwCount;
3666             m_MethodDefToPropertyInfoMap.dwCount = m_MethodDefToDescMap.dwCount;
3667         }
3668         else
3669         {
3670             m_GenericTypeDefToCanonMethodTableMap.dwCount = 0;
3671             m_MethodDefToPropertyInfoMap.dwCount = 0;
3672         }
3673     }
3674
3675     S_SIZE_T nTotal;
3676
3677     nTotal += m_TypeDefToMethodTableMap.dwCount;
3678     nTotal += m_TypeRefToMethodTableMap.dwCount;
3679     nTotal += m_MethodDefToDescMap.dwCount;
3680     nTotal += m_FieldDefToDescMap.dwCount;
3681     nTotal += m_GenericParamToDescMap.dwCount;
3682     nTotal += m_GenericTypeDefToCanonMethodTableMap.dwCount;
3683     nTotal += m_FileReferencesMap.dwCount;
3684     nTotal += m_ManifestModuleReferencesMap.dwCount;
3685     nTotal += m_MethodDefToPropertyInfoMap.dwCount;
3686
3687     _ASSERTE (m_pAssembly && m_pAssembly->GetLowFrequencyHeap());
3688     pTable = (PTR_TADDR)(void*)m_pAssembly->GetLowFrequencyHeap()->AllocMem(nTotal * S_SIZE_T(sizeof(TADDR)));
3689
3690     // Note: Memory allocated on loader heap is zero filled
3691     // memset(pTable, 0, nTotal * sizeof(void*));
3692
3693     m_TypeDefToMethodTableMap.pNext  = NULL;
3694     m_TypeDefToMethodTableMap.supportedFlags = TYPE_DEF_MAP_ALL_FLAGS;
3695     m_TypeDefToMethodTableMap.pTable = pTable;
3696
3697     m_TypeRefToMethodTableMap.pNext  = NULL;
3698     m_TypeRefToMethodTableMap.supportedFlags = TYPE_REF_MAP_ALL_FLAGS;
3699     m_TypeRefToMethodTableMap.pTable = &pTable[m_TypeDefToMethodTableMap.dwCount];
3700
3701     m_MethodDefToDescMap.pNext  = NULL;
3702     m_MethodDefToDescMap.supportedFlags = METHOD_DEF_MAP_ALL_FLAGS;
3703     m_MethodDefToDescMap.pTable = &m_TypeRefToMethodTableMap.pTable[m_TypeRefToMethodTableMap.dwCount];
3704
3705     m_FieldDefToDescMap.pNext  = NULL;
3706     m_FieldDefToDescMap.supportedFlags = FIELD_DEF_MAP_ALL_FLAGS;
3707     m_FieldDefToDescMap.pTable = &m_MethodDefToDescMap.pTable[m_MethodDefToDescMap.dwCount];
3708
3709     m_GenericParamToDescMap.pNext  = NULL;
3710     m_GenericParamToDescMap.supportedFlags = GENERIC_PARAM_MAP_ALL_FLAGS;
3711     m_GenericParamToDescMap.pTable = &m_FieldDefToDescMap.pTable[m_FieldDefToDescMap.dwCount];
3712
3713     m_GenericTypeDefToCanonMethodTableMap.pNext  = NULL;
3714     m_GenericTypeDefToCanonMethodTableMap.supportedFlags = GENERIC_TYPE_DEF_MAP_ALL_FLAGS;
3715     m_GenericTypeDefToCanonMethodTableMap.pTable = &m_GenericParamToDescMap.pTable[m_GenericParamToDescMap.dwCount];
3716
3717     m_FileReferencesMap.pNext  = NULL;
3718     m_FileReferencesMap.supportedFlags = FILE_REF_MAP_ALL_FLAGS;
3719     m_FileReferencesMap.pTable = &m_GenericTypeDefToCanonMethodTableMap.pTable[m_GenericTypeDefToCanonMethodTableMap.dwCount];
3720
3721     m_ManifestModuleReferencesMap.pNext  = NULL;
3722     m_ManifestModuleReferencesMap.supportedFlags = MANIFEST_MODULE_MAP_ALL_FLAGS;
3723     m_ManifestModuleReferencesMap.pTable = &m_FileReferencesMap.pTable[m_FileReferencesMap.dwCount];
3724
3725     m_MethodDefToPropertyInfoMap.pNext = NULL;
3726     m_MethodDefToPropertyInfoMap.supportedFlags = PROPERTY_INFO_MAP_ALL_FLAGS;
3727     m_MethodDefToPropertyInfoMap.pTable = &m_ManifestModuleReferencesMap.pTable[m_ManifestModuleReferencesMap.dwCount];
3728 }
3729
3730
3731 //
3732 // FreeClassTables frees the classes in the module
3733 //
3734
3735 void Module::FreeClassTables()
3736 {
3737     CONTRACTL
3738     {
3739         INSTANCE_CHECK;
3740         NOTHROW;
3741         GC_TRIGGERS;
3742         MODE_ANY;
3743     }
3744     CONTRACTL_END;
3745
3746     if (m_dwTransientFlags & CLASSES_FREED)
3747         return;
3748
3749     FastInterlockOr(&m_dwTransientFlags, CLASSES_FREED);
3750
3751     // disable ibc here because it can cause errors during the destruction of classes
3752     IBCLoggingDisabler disableLogging;
3753             
3754 #if _DEBUG 
3755     DebugLogRidMapOccupancy();
3756 #endif
3757
3758     //
3759     // Free the types filled out in the TypeDefToEEClass map
3760     //
3761
3762     // Go through each linked block
3763     LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
3764     while (typeDefIter.Next())
3765     {
3766         MethodTable * pMT = typeDefIter.GetElement();
3767
3768         if (pMT != NULL && pMT->IsRestored())
3769         {
3770             pMT->GetClass()->Destruct(pMT);
3771         }
3772     }
3773
3774     // Now do the same for constructed types (arrays and instantiated generic types)
3775     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
3776     {                 // separate AllocMemTracker. Though you're supposed to destruct everything else before destructing the AllocMemTracker, this is an easy invariant to break so
3777                       // we'll play extra safe on this end.
3778         if (m_pAvailableParamTypes != NULL)
3779         {
3780             EETypeHashTable::Iterator it(m_pAvailableParamTypes);
3781             EETypeHashEntry *pEntry;
3782             while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
3783             {
3784                 TypeHandle th = pEntry->GetTypeHandle();
3785
3786                 if (!th.IsRestored())
3787                     continue;
3788
3789 #ifdef FEATURE_COMINTEROP
3790                 // Some MethodTables/TypeDescs have COM interop goo attached to them which must be released
3791                 if (!th.IsTypeDesc())
3792                 {
3793                     MethodTable *pMT = th.AsMethodTable();
3794                     if (pMT->HasCCWTemplate() && (!pMT->IsZapped() || pMT->GetZapModule() == this))
3795                     {
3796                         // code:MethodTable::GetComCallWrapperTemplate() may go through canonical methodtable indirection cell.
3797                         // The module load could be aborted before completing code:FILE_LOAD_EAGER_FIXUPS phase that's responsible 
3798                         // for resolving pre-restored indirection cells, so we have to check for it here explicitly.
3799                         if (CORCOMPILE_IS_POINTER_TAGGED(pMT->GetCanonicalMethodTableFixup()))
3800                             continue;
3801
3802                         ComCallWrapperTemplate *pTemplate = pMT->GetComCallWrapperTemplate();
3803                         if (pTemplate != NULL)
3804                         {
3805                             pTemplate->Release();
3806                         }
3807                     }
3808                 }
3809                 else if (th.IsArray())
3810                 {
3811                     ComCallWrapperTemplate *pTemplate = th.AsArray()->GetComCallWrapperTemplate();
3812                     if (pTemplate != NULL)
3813                     {
3814                         pTemplate->Release();
3815                     }
3816                 }
3817 #endif // FEATURE_COMINTEROP
3818
3819                 // We need to call destruct on instances of EEClass whose "canonical" dependent lives in this table
3820                 // There is nothing interesting to destruct on array EEClass
3821                 if (!th.IsTypeDesc())
3822                 {
3823                     MethodTable * pMT = th.AsMethodTable();
3824                     if (pMT->IsCanonicalMethodTable() && (!pMT->IsZapped() || pMT->GetZapModule() == this))
3825                         pMT->GetClass()->Destruct(pMT);
3826                 }
3827             }
3828         }
3829     }
3830 }
3831
3832 #endif // !DACCESS_COMPILE
3833
3834 ClassLoader *Module::GetClassLoader()
3835 {
3836     WRAPPER_NO_CONTRACT;
3837     SUPPORTS_DAC;
3838     _ASSERTE(m_pAssembly != NULL);
3839     return m_pAssembly->GetLoader();
3840 }
3841
3842 PTR_BaseDomain Module::GetDomain()
3843 {
3844     WRAPPER_NO_CONTRACT;
3845     SUPPORTS_DAC;
3846     _ASSERTE(m_pAssembly != NULL);
3847     return m_pAssembly->GetDomain();
3848 }
3849
3850 #ifndef DACCESS_COMPILE 
3851
3852 IAssemblySecurityDescriptor *Module::GetSecurityDescriptor()
3853 {
3854     WRAPPER_NO_CONTRACT;
3855     _ASSERTE(m_pAssembly != NULL);
3856     return m_pAssembly->GetSecurityDescriptor();
3857 }
3858
3859 #ifndef CROSSGEN_COMPILE
3860 void Module::StartUnload()
3861 {
3862     WRAPPER_NO_CONTRACT;
3863 #ifdef PROFILING_SUPPORTED 
3864     {
3865         BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
3866         if (!IsBeingUnloaded())
3867         {
3868             // Profiler is causing some peripheral class loads. Probably this just needs
3869             // to be turned into a Fault_not_fatal and moved to a specific place inside the profiler.
3870             EX_TRY
3871             {
3872                 GCX_PREEMP();
3873                 g_profControlBlock.pProfInterface->ModuleUnloadStarted((ModuleID) this);
3874             }
3875             EX_CATCH
3876             {
3877             }
3878             EX_END_CATCH(SwallowAllExceptions);
3879         }
3880         END_PIN_PROFILER();
3881     }
3882 #endif // PROFILING_SUPPORTED
3883 #ifdef FEATURE_PREJIT 
3884     // Write out the method profile data
3885     /*hr=*/WriteMethodProfileDataLogFile(true);
3886 #endif // FEATURE_PREJIT
3887     SetBeingUnloaded();
3888 }
3889 #endif // CROSSGEN_COMPILE
3890
3891 void Module::ReleaseILData(void)
3892 {
3893     WRAPPER_NO_CONTRACT;
3894
3895     ReleaseISymUnmanagedReader();
3896 }
3897
3898
3899 #ifdef FEATURE_FUSION
3900
3901 //
3902 // Module::FusionCopyPDBs asks Fusion to copy PDBs for a given
3903 // assembly if they need to be copied. This is for the case where a PE
3904 // file is shadow copied to the Fusion cache. Fusion needs to be told
3905 // to take the time to copy the PDB, too.
3906 //
3907 STDAPI CopyPDBs(IAssembly *pAsm); // private fusion API
3908 void Module::FusionCopyPDBs(LPCWSTR moduleName)
3909 {
3910     CONTRACTL
3911     {
3912         INSTANCE_CHECK;
3913         NOTHROW;
3914         GC_NOTRIGGER;
3915         MODE_ANY;
3916     }
3917     CONTRACTL_END;
3918
3919     Assembly *pAssembly = GetAssembly();
3920
3921     // Just return if we've already done this for this Module's
3922     // Assembly.
3923     if ((pAssembly->GetDebuggerInfoBits() & DACF_PDBS_COPIED) ||
3924         (pAssembly->GetFusionAssembly() == NULL))
3925     {
3926         LOG((LF_CORDB, LL_INFO10,
3927              "Don't need to copy PDB's for module %S\n",
3928              moduleName));
3929
3930         return;
3931     }
3932
3933     LOG((LF_CORDB, LL_INFO10,
3934          "Attempting to copy PDB's for module %S\n", moduleName));
3935
3936     HRESULT hr;
3937     hr = CopyPDBs(pAssembly->GetFusionAssembly());
3938     LOG((LF_CORDB, LL_INFO10,
3939             "Fusion.dll!CopyPDBs returned hr=0x%08x for module 0x%08x\n",
3940             hr, this));
3941
3942     // Remember that we've copied the PDBs for this assembly.
3943     pAssembly->SetCopiedPDBs();
3944 }
3945
3946 // This function will return PDB stream if exist.
3947 // It is the caller responsibility to call release on *ppStream after a successful
3948 // result.
3949 // We will first check to see if we have a cached pdb stream available. If not,
3950 // we will ask fusion which in terms to ask host vis HostProvideAssembly. Host may
3951 // decide to provide one or not.
3952 //
3953 HRESULT Module::GetHostPdbStream(IStream **ppStream)
3954 {
3955     CONTRACTL
3956     {
3957         NOTHROW;
3958         if(GetThread()) {GC_TRIGGERS;} else {GC_NOTRIGGER;}
3959     }
3960     CONTRACTL_END
3961
3962     HRESULT hr = NOERROR;
3963
3964     _ASSERTE(ppStream);
3965
3966     *ppStream = NULL;
3967
3968     if (m_file->IsIStream() == false)
3969     {
3970         // not a host stream
3971         return E_FAIL;
3972     }
3973
3974     // Maybe fusion can ask our host. This will give us back a PDB stream if
3975     // host decides to provide one.
3976     //
3977     if (m_file->IsAssembly())
3978     {
3979         GCX_PREEMP();
3980         hr = ((PEAssembly*)m_file)->GetIHostAssembly()->GetAssemblyDebugStream(ppStream);
3981     }
3982     else
3983     {
3984         _ASSERTE(m_file->IsModule());
3985         IHostAssemblyModuleImport *pIHAMI;
3986         MAKE_WIDEPTR_FROMUTF8_NOTHROW(pName, m_file->GetSimpleName());
3987         if (pName == NULL)
3988             return E_OUTOFMEMORY;
3989         IfFailRet(m_file->GetAssembly()->GetIHostAssembly()->GetModuleByName(pName, &pIHAMI));
3990         hr = pIHAMI->GetModuleDebugStream(ppStream);
3991     }
3992     return hr;
3993 }
3994
3995 #endif
3996
3997 //---------------------------------------------------------------------------------------
3998 //
3999 // Simple wrapper around calling IsAfContentType_WindowsRuntime() against the flags
4000 // returned from the PEAssembly's GetFlagsNoTrigger()
4001 //
4002 // Return Value:
4003 //     nonzero iff we successfully determined pModule is a WinMD. FALSE if pModule is not
4004 //     a WinMD, or we fail trying to find out.
4005 //
4006 BOOL Module::IsWindowsRuntimeModule()
4007 {
4008     CONTRACTL 
4009     {
4010         NOTHROW;
4011         GC_NOTRIGGER;
4012         CAN_TAKE_LOCK;     // Accesses metadata directly, which takes locks
4013         MODE_ANY;
4014     } 
4015     CONTRACTL_END;
4016
4017     BOOL fRet = FALSE;
4018
4019     DWORD dwFlags;
4020
4021     if (FAILED(GetAssembly()->GetManifestFile()->GetFlagsNoTrigger(&dwFlags)))
4022         return FALSE;
4023
4024     return IsAfContentType_WindowsRuntime(dwFlags);
4025 }
4026
4027 BOOL Module::IsInCurrentVersionBubble()
4028 {
4029     LIMITED_METHOD_CONTRACT;
4030
4031 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
4032     if (!IsCompilationProcess())
4033         return TRUE;
4034
4035     // The module being compiled is always part of the current version bubble
4036     AppDomain * pAppDomain = GetAppDomain();
4037     if (pAppDomain->IsCompilationDomain() && pAppDomain->ToCompilationDomain()->GetTargetModule() == this)
4038         return TRUE;
4039
4040     if (IsReadyToRunCompilation())
4041         return FALSE;
4042
4043 #ifdef FEATURE_COMINTEROP
4044     if (g_fNGenWinMDResilient)
4045         return !GetAssembly()->IsWinMD();
4046 #endif
4047
4048     return TRUE;
4049 #else // FEATURE_NATIVE_IMAGE_GENERATION
4050     return TRUE;
4051 #endif // FEATURE_NATIVE_IMAGE_GENERATION
4052 }
4053
4054 //---------------------------------------------------------------------------------------
4055 //
4056 // WinMD-aware helper to grab a readable public metadata interface. Any place that thinks
4057 // it wants to use Module::GetRWImporter + QI now should use this wrapper instead.
4058 //
4059 // Arguments:
4060 //      * dwOpenFlags - Combo from CorOpenFlags. Better not contain ofWrite!
4061 //      * riid - Public IID requested
4062 //      * ppvInterface - [out] Requested interface. On success, *ppvInterface is returned
4063 //          refcounted; caller responsible for Release.
4064 //
4065 // Return Value:
4066 //      HRESULT indicating success or failure.
4067 //
4068 HRESULT Module::GetReadablePublicMetaDataInterface(DWORD dwOpenFlags, REFIID riid, LPVOID * ppvInterface)
4069 {
4070     CONTRACTL 
4071     {
4072         NOTHROW;
4073         GC_NOTRIGGER;
4074         CAN_TAKE_LOCK;     // IsWindowsRuntimeModule accesses metadata directly, which takes locks
4075         MODE_ANY;
4076     } 
4077     CONTRACTL_END;
4078
4079     _ASSERTE((dwOpenFlags & ofWrite) == 0);
4080
4081     // Temporary place to store public, AddRef'd interface pointers
4082     ReleaseHolder<IUnknown> pIUnkPublic;
4083
4084     // Temporary place to store the IUnknown from which we'll do the final QI to get the
4085     // requested public interface.  Any assignment to pIUnk assumes pIUnk does not need
4086     // to do a Release() (either the interface was internal and not AddRef'd, or was
4087     // public and will be released by the above holder).
4088     IUnknown * pIUnk = NULL;
4089     
4090     HRESULT hr = S_OK;
4091
4092     // Normally, we just get an RWImporter to do the QI on, and we're on our way.
4093     EX_TRY
4094     {
4095         pIUnk = GetRWImporter();
4096     }
4097     EX_CATCH_HRESULT_NO_ERRORINFO(hr);
4098
4099     if (FAILED(hr) && IsWindowsRuntimeModule())
4100     {
4101         // WinMD modules don't like creating RW importers.   They also (currently)
4102         // have no plumbing to get to their public metadata interfaces from the
4103         // Module.  So we actually have to start from scratch at the dispenser.
4104
4105         // To start with, get a dispenser, and get the metadata memory blob we've
4106         // already loaded.  If either of these fail, just return the error HRESULT
4107         // from the above GetRWImporter() call.
4108
4109         // We'll get an addref'd IMetaDataDispenser, so use a holder to release it
4110         ReleaseHolder<IMetaDataDispenser> pDispenser;
4111         if (FAILED(InternalCreateMetaDataDispenser(IID_IMetaDataDispenser, &pDispenser)))
4112         {
4113             _ASSERTE(FAILED(hr));
4114             return hr;
4115         }
4116
4117         COUNT_T cbMetadata = 0;
4118         PTR_CVOID pvMetadata = GetAssembly()->GetManifestFile()->GetLoadedMetadata(&cbMetadata);
4119         if ((pvMetadata == NULL) || (cbMetadata == 0))
4120         {
4121             _ASSERTE(FAILED(hr));
4122             return hr;
4123         }
4124
4125         // Now that the pieces are ready, we can use the riid specified by the
4126         // profiler in this call to the dispenser to get the requested interface. If
4127         // this fails, then this is the interesting HRESULT for the caller to see.
4128         // 
4129         // We'll get an AddRef'd public interface, so use a holder to release it
4130         hr = pDispenser->OpenScopeOnMemory(
4131             pvMetadata, 
4132             cbMetadata, 
4133             (dwOpenFlags | ofReadOnly),         // Force ofReadOnly on behalf of the profiler
4134             riid, 
4135             &pIUnkPublic);
4136         if (FAILED(hr))
4137             return hr;
4138
4139         // Set pIUnk so we can do the final QI from it below as we do in the other
4140         // cases.
4141         pIUnk = pIUnkPublic;
4142     }
4143
4144     // Get the requested interface
4145     if (SUCCEEDED(hr) && (ppvInterface != NULL))
4146     {
4147         _ASSERTE(pIUnk != NULL);
4148         hr = pIUnk->QueryInterface(riid, (void **) ppvInterface);
4149     }
4150
4151     return hr;
4152 }
4153
4154 // a special token that indicates no reader could be created - don't try again
4155 static ISymUnmanagedReader* const k_pInvalidSymReader = (ISymUnmanagedReader*)0x1;
4156
4157 #if defined(FEATURE_ISYM_READER) && !defined(CROSSGEN_COMPILE)
4158 ISymUnmanagedReader *Module::GetISymUnmanagedReaderNoThrow(void)
4159 {
4160     CONTRACT(ISymUnmanagedReader *)
4161     {
4162         INSTANCE_CHECK;
4163         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
4164         NOTHROW;
4165         WRAPPER(GC_TRIGGERS);
4166         MODE_ANY;
4167     }
4168     CONTRACT_END;
4169
4170     ISymUnmanagedReader *ret = NULL;
4171
4172     EX_TRY
4173     {
4174         ret = GetISymUnmanagedReader();
4175     }
4176     EX_CATCH
4177     {
4178         // We swallow any exception and say that we simply couldn't get a reader by returning NULL.
4179         // The only type of error that should be possible here is OOM.
4180         /* DISABLED due to Dev10 bug 619495 
4181         CONSISTENCY_CHECK_MSG(
4182             GET_EXCEPTION()->GetHR() == E_OUTOFMEMORY, 
4183             "Exception from GetISymUnmanagedReader");
4184          */
4185     }
4186     EX_END_CATCH(RethrowTerminalExceptions);
4187
4188     RETURN (ret);
4189 }
4190
4191 ISymUnmanagedReader *Module::GetISymUnmanagedReader(void)
4192 {
4193     CONTRACT(ISymUnmanagedReader *)
4194     {
4195         INSTANCE_CHECK;
4196         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
4197         PRECONDITION(Security::IsResolved(GetAssembly()));
4198         THROWS;
4199         WRAPPER(GC_TRIGGERS);
4200         MODE_ANY;
4201     }
4202     CONTRACT_END;
4203
4204     // No symbols for resource modules
4205     if (IsResource())
4206         RETURN NULL;
4207
4208     if (g_fEEShutDown)
4209         RETURN NULL;
4210
4211     // Verify that symbol reading is permitted for this module.
4212     // If we know we've already created a symbol reader, don't bother checking.  There is
4213     // no advantage to allowing symbol reading to be turned off if we've already created the reader.
4214     // Note that we can't just put this code in the creation block below because we might have to
4215     // call managed code to resolve security policy, and we can't do that while holding a lock.
4216     // There is no disadvantage other than a minor perf cost to calling this unnecessarily, so the
4217     // race on m_pISymUnmanagedReader here is OK.  The perf cost is minor because the only real
4218     // work is done by the security system which caches the result.
4219     if( m_pISymUnmanagedReader == NULL && !IsSymbolReadingEnabled() )
4220         RETURN NULL;
4221     
4222     // Take the lock for the m_pISymUnmanagedReader
4223     // This ensures that we'll only ever attempt to create one reader at a time, and we won't
4224     // create a reader if we're in the middle of destroying one that has become stale.
4225     // Actual access to the reader can safely occur outside the lock as long as it has its own
4226     // AddRef which we take inside the lock at the bottom of this method.
4227     CrstHolder holder(&m_ISymUnmanagedReaderCrst);
4228
4229     UINT lastErrorMode = 0;
4230
4231     // If we haven't created a reader yet, do so now
4232     if (m_pISymUnmanagedReader == NULL)
4233     {
4234         // Mark our reader as invalid so that if we fail to create the reader
4235         // (including if an exception is thrown), we won't keep trying.
4236         m_pISymUnmanagedReader = k_pInvalidSymReader;
4237
4238         // There are 4 main cases here:
4239         //  1. Assembly is on disk and we'll get the symbols from a file next to the assembly
4240         //  2. Assembly is provided by the host and we'll get the symbols from the host
4241         //  3. Assembly was loaded in-memory (by byte array or ref-emit), and symbols were
4242         //      provided along with it.
4243         //  4. Assembly was loaded in-memory but no symbols were provided.
4244
4245         // Determine whether we should be looking in memory for the symbols (cases 2 & 3)
4246         bool fInMemorySymbols = ( m_file->IsIStream() || GetInMemorySymbolStream() );
4247         if( !fInMemorySymbols && m_file->GetPath().IsEmpty() )
4248         {
4249             // Case 4.  We don't have a module path, an IStream or an in memory symbol stream, 
4250             // so there is no-where to try and get symbols from.
4251             RETURN (NULL);
4252         }
4253
4254         // Create a binder to find the reader.
4255         //
4256         // <REVISIT_TODO>@perf: this is slow, creating and destroying the binder every
4257         // time. We should cache this somewhere, but I'm not 100% sure
4258         // where right now...</REVISIT_TODO>
4259         HRESULT hr = S_OK;
4260
4261         SafeComHolder<ISymUnmanagedBinder> pBinder;
4262
4263         if (g_pDebugInterface == NULL)
4264         {
4265             // @TODO: this is reachable when debugging!
4266             UNREACHABLE_MSG("About to CoCreateInstance!  This code should not be "
4267                             "reachable or needs to be reimplemented for CoreCLR!");
4268         }
4269
4270         if (this->GetInMemorySymbolStreamFormat() == eSymbolFormatILDB)
4271         {
4272             // We've got in-memory ILDB symbols, create the ILDB symbol binder
4273             // Note that in this case, we must be very careful not to use diasymreader.dll
4274             // at all - we don't trust it, and shouldn't run any code in it
4275             IfFailThrow(IldbSymbolsCreateInstance(CLSID_CorSymBinder_SxS,
4276                                   IID_ISymUnmanagedBinder,
4277                                   (void**)&pBinder));
4278         }
4279         else
4280         {
4281             // We're going to be working with PDB format symbols
4282             // Attempt to coCreate the symbol binder.
4283             // CoreCLR supports not having a symbol reader installed, so this is expected there.
4284             // On desktop, the framework installer is supposed to install diasymreader.dll as well
4285             // and so this shouldn't happen.
4286             hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS,
4287                                         NATIVE_SYMBOL_READER_DLL,
4288                                         IID_ISymUnmanagedBinder,
4289                                         (void**)&pBinder,
4290                                         NULL);
4291             if (FAILED(hr))
4292             {
4293                 RETURN (NULL);
4294             }
4295
4296         }
4297
4298         LOG((LF_CORDB, LL_INFO10, "M::GISUR: Created binder\n"));
4299
4300         // Note: we change the error mode here so we don't get any popups as the PDB symbol reader attempts to search the
4301         // hard disk for files.
4302         lastErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);
4303
4304         SafeComHolder<ISymUnmanagedReader> pReader;
4305
4306         if (fInMemorySymbols) 
4307         {
4308             SafeComHolder<IStream> pIStream( NULL );
4309
4310             // If debug stream is already specified, don't bother to go through fusion
4311             // This is the common case for case 2 (hosted modules) and case 3 (Ref.Emit).
4312             if (GetInMemorySymbolStream() )
4313             {
4314                 
4315                 if( IsReflection() )
4316                 {
4317                     // If this is Reflection.Emit, we must clone the stream because another thread may 
4318                     // update it when someone is using the reader we create here leading to AVs.
4319                     // Note that the symbol stream should be up to date since we flush the writer
4320                     // after every addition in Module::AddClass.
4321                     IfFailThrow(GetInMemorySymbolStream()->Clone(&pIStream));
4322                 }
4323                 else
4324                 {
4325                     // The stream is not changing. Just add-ref to it.
4326                     pIStream = GetInMemorySymbolStream();
4327                     pIStream->AddRef();
4328                 }
4329             }
4330 #ifdef FEATURE_FUSION
4331             else
4332             {
4333                 // Verified this above.
4334                 _ASSERTE(m_file->IsIStream());
4335
4336                 // Case 2: get assembly from host.
4337                 // This commonly would be cached already as GetInMemorySymbolStream() in code:Module.FetchPdbsFromHost,
4338                 // but may not be cached if the host didn't provide the PDBs at the time. 
4339                 hr = GetHostPdbStream(&pIStream);
4340             }
4341 #endif
4342             if (SUCCEEDED(hr))
4343             {
4344                 hr = pBinder->GetReaderFromStream(GetRWImporter(), pIStream, &pReader);
4345             }
4346         }
4347         else
4348         {
4349             // The assembly is on disk, so try and load symbols based on the path to the assembly (case 1)
4350             const SString &path = m_file->GetPath();
4351
4352             // Call Fusion to ensure that any PDB's are shadow copied before
4353             // trying to get a symbol reader. This has to be done once per
4354             // Assembly.
4355 #ifdef FEATURE_FUSION
4356             FusionCopyPDBs(path);
4357 #endif
4358             // for this to work with winmds we cannot simply call GetRWImporter() as winmds are RO
4359             // and thus don't implement the RW interface. so we call this wrapper function which knows 
4360             // how to get a IMetaDataImport interface regardless of the underlying module type.
4361             ReleaseHolder<IUnknown> pUnk = NULL;
4362             hr = GetReadablePublicMetaDataInterface(ofReadOnly, IID_IMetaDataImport, &pUnk);
4363             if (SUCCEEDED(hr))
4364                 hr = pBinder->GetReaderForFile(pUnk, path, NULL, &pReader);
4365         }
4366
4367         SetErrorMode(lastErrorMode);
4368
4369         if (SUCCEEDED(hr))
4370         {
4371             m_pISymUnmanagedReader = pReader.Extract();
4372             LOG((LF_CORDB, LL_INFO10, "M::GISUR: Loaded symbols for module %S\n", GetDebugName()));
4373         }
4374         else
4375         {
4376             // We failed to create the reader, don't try again next time
4377             LOG((LF_CORDB, LL_INFO10, "M::GISUR: Failed to load symbols for module %S\n", GetDebugName()));
4378             _ASSERTE( m_pISymUnmanagedReader == k_pInvalidSymReader );
4379         }
4380
4381     } // if( m_pISymUnmanagedReader == NULL )
4382
4383     // If we previously failed to create the reader, return NULL
4384     if (m_pISymUnmanagedReader == k_pInvalidSymReader)
4385     {
4386         RETURN (NULL);
4387     }
4388
4389     // Success - return an AddRef'd copy of the reader
4390     m_pISymUnmanagedReader->AddRef();
4391     RETURN (m_pISymUnmanagedReader);
4392 }
4393 #endif // FEATURE_ISYM_READER && !CROSSGEN_COMPILE
4394
4395 BOOL Module::IsSymbolReadingEnabled()
4396 {
4397     CONTRACTL
4398     {
4399         INSTANCE_CHECK;
4400         THROWS;
4401         GC_TRIGGERS;
4402         MODE_ANY;
4403     }
4404     CONTRACTL_END;
4405
4406     // The only time we need symbols available is for debugging and taking stack traces,
4407     // neither of which can be done if the assembly can't run. The advantage of being strict
4408     // is that there is a perf penalty adding types to a module if you must support reading
4409     // symbols at any time. If symbols don't need to be accesible then we can
4410     // optimize by only commiting symbols when the assembly is saved to disk. See DDB 671107.
4411     if(!GetAssembly()->HasRunAccess())
4412     {
4413         return FALSE;
4414     }
4415
4416     // If the module has symbols in-memory (eg. RefEmit) that are in ILDB
4417     // format, then there isn't any reason not to supply them.  The reader
4418     // code is always available, and we trust it's security.
4419     if (this->GetInMemorySymbolStreamFormat() == eSymbolFormatILDB)
4420     {
4421         return TRUE;
4422     }
4423
4424 #ifdef DEBUGGING_SUPPORTED 
4425     if (!g_pDebugInterface)
4426     {
4427         // if debugging is disabled (no debug pack installed), do not load symbols
4428         // This is done for two reasons.  We don't completely trust the security of
4429         // the diasymreader.dll code, so we don't want to use it in mainline scenarios.
4430         // Secondly, there's not reason that diasymreader.dll will even necssarily be
4431         // be on the machine if the debug pack isn't installed.
4432         return FALSE;
4433     }
4434 #endif // DEBUGGING_SUPPORTED
4435
4436 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
4437     // See if there is an explicit policy configuration overriding our default.
4438     // This can be set by the SymbolReadingPolicy config switch or by a host via
4439     // ICLRDebugManager.AllowFileLineInfo.
4440     ESymbolReadingPolicy policy = CCLRDebugManager::GetSymbolReadingPolicy();
4441     if( policy == eSymbolReadingAlways )
4442     {
4443         return TRUE;
4444     }
4445     else if( policy == eSymbolReadingNever )
4446     {
4447         return FALSE;
4448     }
4449     _ASSERTE( policy == eSymbolReadingFullTrustOnly );
4450 #endif // FEATURE_INCLUDE_ALL_INTERFACES
4451
4452     // Default policy - only read symbols corresponding to full-trust assemblies.
4453     // Note that there is no strong (cryptographic) connection between a symbol file and its assembly.
4454         // The intent here is just to ensure that the common high-risk scenarios (AppLaunch, etc)
4455         // will never be able to load untrusted PDB files.
4456     // 
4457         if (GetSecurityDescriptor()->IsFullyTrusted())
4458         {
4459             return TRUE;
4460         }
4461     return FALSE;
4462 }
4463
4464 // At this point, this is only called when we're creating an appdomain
4465 // out of an array of bytes, so we'll keep the IStream that we create
4466 // around in case the debugger attaches later (including detach & re-attach!)
4467 void Module::SetSymbolBytes(LPCBYTE pbSyms, DWORD cbSyms)
4468 {
4469     STANDARD_VM_CONTRACT;
4470
4471     // Create a IStream from the memory for the syms.
4472     SafeComHolder<CGrowableStream> pStream(new CGrowableStream());
4473
4474     // Do not need to AddRef the CGrowableStream because the constructor set it to 1
4475     // ref count already. The Module will keep a copy for its own use.
4476
4477     // Make sure to set the symbol stream on the module before
4478     // attempting to send UpdateModuleSyms messages up for it.
4479     SetInMemorySymbolStream(pStream, eSymbolFormatPDB);
4480
4481     // This can only be called when the module is being created.  No-one should have
4482     // tried to use the symbols yet, and so there should not be a reader.
4483     // If instead, we wanted to call this when a reader could have been created, we need to 
4484     // serialize access by taking the reader lock, and flush the old reader by calling 
4485     // code:Module.ReleaseISymUnmanagedReader
4486     _ASSERTE( m_pISymUnmanagedReader == NULL );
4487     
4488 #ifdef LOGGING 
4489     LPCWSTR pName = NULL;
4490     pName = GetDebugName();
4491 #endif // LOGGING
4492
4493     ULONG cbWritten;
4494     DWORD dwError = pStream->Write((const void *)pbSyms,
4495                                (ULONG)cbSyms,
4496                                                 &cbWritten);
4497     IfFailThrow(HRESULT_FROM_WIN32(dwError));
4498
4499 #if PROFILING_SUPPORTED && !defined(CROSSGEN_COMPILE)
4500     BEGIN_PIN_PROFILER(CORProfilerInMemorySymbolsUpdatesEnabled());
4501     {
4502         g_profControlBlock.pProfInterface->ModuleInMemorySymbolsUpdated((ModuleID) this);
4503     }
4504     END_PIN_PROFILER();
4505 #endif //PROFILING_SUPPORTED && !defined(CROSSGEN_COMPILE)
4506
4507     ETW::CodeSymbolLog::EmitCodeSymbols(this);
4508
4509     // Tell the debugger that symbols have been loaded for this
4510     // module.  We iterate through all domains which contain this
4511     // module's assembly, and send a debugger notify for each one.
4512     // <REVISIT_TODO>@perf: it would scale better if we directly knew which domains
4513     // the assembly was loaded in.</REVISIT_TODO>
4514     if (CORDebuggerAttached())
4515     {
4516         AppDomainIterator i(FALSE);
4517
4518         while (i.Next())
4519         {
4520             AppDomain *pDomain = i.GetDomain();
4521
4522             if (pDomain->IsDebuggerAttached() && (GetDomain() == SystemDomain::System() ||
4523                                                   pDomain->ContainsAssembly(m_pAssembly)))
4524             {
4525                 g_pDebugInterface->SendUpdateModuleSymsEventAndBlock(this, pDomain);
4526             }
4527         }
4528     }
4529 }
4530
4531 // Clear any cached symbol reader
4532 void Module::ReleaseISymUnmanagedReader(void)
4533 {
4534     CONTRACTL
4535     {
4536         NOTHROW;
4537         GC_NOTRIGGER;
4538         MODE_ANY;
4539         FORBID_FAULT;
4540     }
4541     CONTRACTL_END;
4542
4543     // Caller is responsible for taking the reader lock if the call could occur when
4544     // other threads are using or creating the reader
4545     if( m_pISymUnmanagedReader != NULL )
4546     {
4547         // If we previously failed to create a reader, don't attempt to release it
4548         // but do clear it out so that we can try again (eg. symbols may have changed)
4549         if( m_pISymUnmanagedReader != k_pInvalidSymReader )
4550         {
4551             m_pISymUnmanagedReader->Release();
4552         }
4553         m_pISymUnmanagedReader = NULL;
4554     }
4555 }
4556
4557 // Lazily creates a new IL stub cache for this module.
4558 ILStubCache* Module::GetILStubCache()
4559 {
4560     CONTRACTL
4561     {
4562         THROWS;
4563         GC_NOTRIGGER;
4564         MODE_ANY;
4565         INJECT_FAULT(COMPlusThrowOM(););
4566     }
4567     CONTRACTL_END;
4568
4569     // Use per-AD cache for domain specific modules when not NGENing
4570     BaseDomain *pDomain = GetDomain();
4571     if (!pDomain->IsSharedDomain() && !pDomain->AsAppDomain()->IsCompilationDomain())
4572         return pDomain->AsAppDomain()->GetILStubCache();
4573
4574     if (m_pILStubCache == NULL)
4575     {
4576         ILStubCache *pILStubCache = new ILStubCache(GetLoaderAllocator()->GetHighFrequencyHeap());
4577
4578         if (FastInterlockCompareExchangePointer(&m_pILStubCache, pILStubCache, NULL) != NULL)
4579         {
4580             // some thread swooped in and set the field
4581             delete pILStubCache;
4582         }
4583     }
4584     _ASSERTE(m_pILStubCache != NULL);
4585     return m_pILStubCache;
4586 }
4587
4588 // Called to finish the process of adding a new class with Reflection.Emit
4589 void Module::AddClass(mdTypeDef classdef)
4590 {
4591     CONTRACTL
4592     {
4593         INSTANCE_CHECK;
4594         THROWS;
4595         GC_TRIGGERS;
4596         MODE_PREEMPTIVE;
4597         PRECONDITION(!IsResource());
4598     }
4599     CONTRACTL_END;
4600
4601     // The fake class associated with the module (global fields & functions) needs to be initialized here
4602     // Normal classes are added to the available class hash when their typedef is first created.
4603     if (RidFromToken(classdef) == 0)
4604     {
4605         BuildClassForModule();
4606     }
4607
4608     // Since the module is being modified, the in-memory symbol stream 
4609     // (if any) has probably also been modified. If we support reading the symbols
4610     // then we need to commit the changes to the writer and flush any old readers
4611     // However if we don't support reading then we can skip this which will give
4612     // a substantial perf improvement. See DDB 671107.
4613     if(IsSymbolReadingEnabled())
4614     {
4615         CONSISTENCY_CHECK(IsReflection());   // this is only used for dynamic modules
4616         ISymUnmanagedWriter * pWriter = GetReflectionModule()->GetISymUnmanagedWriter();
4617         if (pWriter != NULL)
4618         {
4619             // Serialize with any concurrent reader creations
4620             // Specifically, if we started creating a reader on one thread, and then updated the
4621             // symbols on another thread, we need to wait until the initial reader creation has
4622             // completed and release it so we don't get stuck with a stale reader.
4623             // Also, if we commit to the stream while we're in the process of creating a reader,
4624             // the reader will get corrupted/incomplete data.
4625             // Note that we must also be in co-operative mode here to ensure the debugger helper
4626             // thread can't be simultaneously reading this stream while the process is synchronized
4627             // (code:Debugger::GetSymbolBytes)
4628             CrstHolder holder(&m_ISymUnmanagedReaderCrst);
4629
4630             // Flush writes to the symbol store to the symbol stream
4631             // Note that we do this when finishing the addition of the class, instead of 
4632             // on-demand in GetISymUnmanagedReader because the writer is not thread-safe.
4633             // Here, we're inside the lock of TypeBuilder.CreateType, and so it's safe to
4634             // manipulate the writer.
4635             SafeComHolderPreemp<ISymUnmanagedWriter3> pWriter3;
4636             HRESULT thr = pWriter->QueryInterface(IID_ISymUnmanagedWriter3, (void**)&pWriter3);
4637             CONSISTENCY_CHECK(SUCCEEDED(thr));
4638             if (SUCCEEDED(thr))
4639             {
4640                 thr = pWriter3->Commit();
4641                 if (SUCCEEDED(thr))
4642                 {
4643                     // Flush any cached symbol reader to ensure we pick up any new symbols
4644                     ReleaseISymUnmanagedReader();
4645                 }
4646             }
4647
4648             // If either the QI or Commit failed
4649             if (FAILED(thr))
4650             {
4651                 // The only way we expect this might fail is out-of-memory.  In that
4652                 // case we silently fail to update the symbol stream with new data, but
4653                 // we leave the existing reader intact.
4654                 CONSISTENCY_CHECK(thr==E_OUTOFMEMORY);
4655             }
4656         }
4657     }
4658 }
4659
4660 //---------------------------------------------------------------------------
4661 // For the global class this builds the table of MethodDescs an adds the rids
4662 // to the MethodDef map.
4663 //---------------------------------------------------------------------------
4664 void Module::BuildClassForModule()
4665 {
4666     CONTRACTL
4667     {
4668         INSTANCE_CHECK;
4669         THROWS;
4670         GC_TRIGGERS;
4671         MODE_ANY;
4672     }
4673     CONTRACTL_END;
4674
4675     IMDInternalImport * pImport = GetMDImport();
4676     DWORD           cFunctions, cFields;
4677
4678     {
4679         // Obtain count of global functions
4680         HENUMInternalHolder hEnum(pImport);
4681         hEnum.EnumGlobalFunctionsInit();
4682         cFunctions = pImport->EnumGetCount(&hEnum);
4683     }
4684
4685     {
4686         // Obtain count of global fields
4687         HENUMInternalHolder hEnum(pImport);
4688         hEnum.EnumGlobalFieldsInit();
4689         cFields = pImport->EnumGetCount(&hEnum);
4690     }
4691
4692     // If we have any work to do...
4693     if (cFunctions > 0 || cFields > 0)
4694     {
4695         COUNTER_ONLY(size_t _HeapSize = 0);
4696
4697         TypeKey typeKey(this, COR_GLOBAL_PARENT_TOKEN);
4698         TypeHandle typeHnd = GetClassLoader()->LoadTypeHandleForTypeKeyNoLock(&typeKey);
4699
4700 #ifdef ENABLE_PERF_COUNTERS 
4701
4702         _HeapSize = GetLoaderAllocator()->GetHighFrequencyHeap()->GetSize();
4703
4704         GetPerfCounters().m_Loading.cbLoaderHeapSize = _HeapSize;
4705 #endif // ENABLE_PERF_COUNTERS
4706
4707     }
4708 }
4709
4710 #endif // !DACCESS_COMPILE
4711
4712 // Returns true iff the debugger should be notified about this module
4713 // 
4714 // Notes:
4715 //   Debugger doesn't need to be notified about modules that can't be executed,
4716 //   like inspection and resource only. These are just pure data.
4717 //   
4718 //   This should be immutable for an instance of a module. That ensures that the debugger gets consistent
4719 //   notifications about it. It this value mutates, than the debugger may miss relevant notifications.
4720 BOOL Module::IsVisibleToDebugger()
4721 {
4722     WRAPPER_NO_CONTRACT; 
4723     SUPPORTS_DAC;
4724
4725     if (IsResource())
4726     {
4727         return FALSE;
4728     }
4729
4730     if (IsIntrospectionOnly())
4731     {
4732         return FALSE;
4733     }
4734
4735
4736     // If for whatever other reason, we can't run it, then don't notify the debugger about it.
4737     Assembly * pAssembly = GetAssembly();
4738     if (!pAssembly->HasRunAccess())
4739     {
4740         return FALSE;
4741     }
4742     return TRUE;
4743 }
4744
4745 PEImageLayout * Module::GetNativeOrReadyToRunImage()
4746 {
4747     LIMITED_METHOD_CONTRACT;
4748
4749 #ifdef FEATURE_READYTORUN
4750     if (IsReadyToRun())
4751         return GetReadyToRunInfo()->GetImage();
4752 #endif
4753
4754     return GetNativeImage();
4755 }
4756
4757 PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSections(COUNT_T *pCount)
4758 {
4759     CONTRACTL
4760     {
4761         NOTHROW;
4762         GC_NOTRIGGER;
4763     }
4764     CONTRACTL_END;
4765
4766 #ifdef FEATURE_READYTORUN
4767     if (IsReadyToRun())
4768         return GetReadyToRunInfo()->GetImportSections(pCount);
4769 #endif
4770
4771     return GetNativeImage()->GetNativeImportSections(pCount);
4772 }
4773
4774 PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSectionFromIndex(COUNT_T index)
4775 {
4776     CONTRACTL
4777     {
4778         NOTHROW;
4779         GC_NOTRIGGER;
4780     }
4781     CONTRACTL_END;
4782
4783 #ifdef FEATURE_READYTORUN
4784     if (IsReadyToRun())
4785         return GetReadyToRunInfo()->GetImportSectionFromIndex(index);
4786 #endif
4787
4788     return GetNativeImage()->GetNativeImportSectionFromIndex(index);
4789 }
4790
4791 PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSectionForRVA(RVA rva)
4792 {
4793     CONTRACTL
4794     {
4795         NOTHROW;
4796         GC_NOTRIGGER;
4797     }
4798     CONTRACTL_END;
4799
4800 #ifdef FEATURE_READYTORUN
4801     if (IsReadyToRun())
4802         return GetReadyToRunInfo()->GetImportSectionForRVA(rva);
4803 #endif
4804
4805     return GetNativeImage()->GetNativeImportSectionForRVA(rva);
4806 }
4807
4808 TADDR Module::GetIL(DWORD target)
4809 {
4810     WRAPPER_NO_CONTRACT;
4811     SUPPORTS_DAC;
4812
4813     if (target == 0)
4814         return NULL;
4815
4816     return m_file->GetIL(target);
4817 }
4818
4819 PTR_VOID Module::GetRvaField(DWORD rva, BOOL fZapped)
4820 {
4821     WRAPPER_NO_CONTRACT;
4822     SUPPORTS_DAC;
4823
4824 #ifdef FEATURE_PREJIT 
4825     if (fZapped && m_file->IsILOnly())
4826     {
4827         return dac_cast<PTR_VOID>(m_file->GetLoadedNative()->GetRvaData(rva,NULL_OK));
4828     }
4829 #endif // FEATURE_PREJIT
4830
4831     return m_file->GetRvaField(rva);
4832 }
4833
4834 #ifndef DACCESS_COMPILE 
4835
4836 CHECK Module::CheckRvaField(RVA field)
4837 {
4838     WRAPPER_NO_CONTRACT;
4839     if (!IsReflection())
4840         CHECK(m_file->CheckRvaField(field));
4841     CHECK_OK;
4842 }
4843
4844 CHECK Module::CheckRvaField(RVA field, COUNT_T size)
4845 {
4846     CONTRACTL
4847     {
4848         STANDARD_VM_CHECK;
4849         CAN_TAKE_LOCK;
4850     }
4851     CONTRACTL_END;
4852
4853     if (!IsReflection())
4854         CHECK(m_file->CheckRvaField(field, size));
4855     CHECK_OK;
4856 }
4857
4858 #endif // !DACCESS_COMPILE
4859
4860 BOOL Module::HasTls()
4861 {
4862     WRAPPER_NO_CONTRACT;
4863
4864     return m_file->HasTls();
4865 }
4866
4867 BOOL Module::IsRvaFieldTls(DWORD rva)
4868 {
4869     WRAPPER_NO_CONTRACT;
4870
4871     return m_file->IsRvaFieldTls(rva);
4872 }
4873
4874 UINT32 Module::GetFieldTlsOffset(DWORD rva)
4875 {
4876     WRAPPER_NO_CONTRACT;
4877
4878     return m_file->GetFieldTlsOffset(rva);
4879 }
4880
4881 UINT32 Module::GetTlsIndex()
4882 {
4883     WRAPPER_NO_CONTRACT;
4884
4885     return m_file->GetTlsIndex();
4886 }
4887
4888 PCCOR_SIGNATURE Module::GetSignature(RVA signature)
4889 {
4890     WRAPPER_NO_CONTRACT;
4891
4892     return m_file->GetSignature(signature);
4893 }
4894
4895 RVA Module::GetSignatureRva(PCCOR_SIGNATURE signature)
4896 {
4897     WRAPPER_NO_CONTRACT;
4898
4899     return m_file->GetSignatureRva(signature);
4900 }
4901
4902
4903
4904 // In DAC builds this function was being called on host addresses which may or may not
4905 // have been marshalled from the target. Such addresses can't be reliably mapped back to
4906 // target addresses, which means we can't tell whether they came from the IL or not
4907 //
4908 // Security note: Any security which you might wish to gain by verifying the origin of
4909 // a signature isn't available in DAC. The attacker can provide a dump which spoofs all
4910 // module ranges. In other words the attacker can make the signature appear to come from
4911 // anywhere, but still violate all the rules that a signature from that location would
4912 // otherwise follow. I am removing this function from DAC in order to prevent anyone from
4913 // getting a false sense of security (in addition to its functional shortcomings)
4914
4915 #ifndef DACCESS_COMPILE
4916 BOOL Module::IsSigInIL(PCCOR_SIGNATURE signature)
4917 {
4918     CONTRACTL
4919     {
4920         INSTANCE_CHECK;
4921         FORBID_FAULT;
4922         MODE_ANY;
4923         NOTHROW;
4924         SO_TOLERANT;
4925         GC_NOTRIGGER;
4926     }
4927     CONTRACTL_END;
4928
4929     return m_file->IsPtrInILImage(signature);
4930 }
4931
4932 #ifdef FEATURE_PREJIT
4933 StubMethodHashTable *Module::GetStubMethodHashTable()
4934 {
4935     CONTRACTL
4936     {
4937         THROWS;
4938         GC_NOTRIGGER;
4939     }
4940     CONTRACTL_END
4941
4942     if (m_pStubMethodHashTable == NULL && SystemDomain::GetCurrentDomain()->IsCompilationDomain())
4943     {
4944         // we only need to create the hash table when NGENing, it is read-only at run-time
4945         AllocMemTracker amTracker;
4946         m_pStubMethodHashTable = StubMethodHashTable::Create(GetLoaderAllocator(), this, METHOD_STUBS_HASH_BUCKETS, &amTracker);
4947         amTracker.SuppressRelease();
4948     }
4949
4950     return m_pStubMethodHashTable;
4951 }
4952 #endif // FEATURE_PREJIT
4953
4954 CHECK Module::CheckSignatureRva(RVA signature)
4955 {
4956     WRAPPER_NO_CONTRACT;
4957     CHECK(m_file->CheckSignatureRva(signature));
4958     CHECK_OK;
4959 }
4960
4961 CHECK Module::CheckSignature(PCCOR_SIGNATURE signature)
4962 {
4963     WRAPPER_NO_CONTRACT;
4964     CHECK(m_file->CheckSignature(signature));
4965     CHECK_OK;
4966 }
4967
4968 void Module::InitializeStringData(DWORD token, EEStringData *pstrData, CQuickBytes *pqb)
4969 {
4970     CONTRACTL
4971     {
4972         INSTANCE_CHECK;
4973         THROWS;
4974         GC_TRIGGERS;
4975         MODE_ANY;
4976         INJECT_FAULT(COMPlusThrowOM());
4977         PRECONDITION(TypeFromToken(token) == mdtString);
4978     }
4979     CONTRACTL_END;
4980
4981     BOOL fIs80Plus;
4982     DWORD dwCharCount;
4983     LPCWSTR pString;
4984     if (FAILED(GetMDImport()->GetUserString(token, &dwCharCount, &fIs80Plus, &pString)) || 
4985         (pString == NULL))
4986     {
4987         THROW_BAD_FORMAT(BFA_BAD_STRING_TOKEN_RANGE, this);
4988     }
4989     
4990 #if !BIGENDIAN 
4991     pstrData->SetStringBuffer(pString);
4992 #else // !!BIGENDIAN
4993     _ASSERTE(pqb != NULL);
4994
4995     LPWSTR pSwapped;
4996
4997     pSwapped = (LPWSTR) pqb->AllocThrows(dwCharCount * sizeof(WCHAR));
4998     memcpy((void*)pSwapped, (void*)pString, dwCharCount*sizeof(WCHAR));
4999     SwapStringLength(pSwapped, dwCharCount);
5000
5001     pstrData->SetStringBuffer(pSwapped);
5002 #endif // !!BIGENDIAN
5003
5004         // MD and String look at this bit in opposite ways.  Here's where we'll do the conversion.
5005         // MD sets the bit to true if the string contains characters greater than 80.
5006         // String sets the bit to true if the string doesn't contain characters greater than 80.
5007
5008     pstrData->SetCharCount(dwCharCount);
5009     pstrData->SetIsOnlyLowChars(!fIs80Plus);
5010 }
5011
5012 #ifndef CROSSGEN_COMPILE
5013
5014 #ifdef FEATURE_PREJIT 
5015 OBJECTHANDLE Module::ResolveStringRefHelper(DWORD token, BaseDomain *pDomain, PTR_CORCOMPILE_IMPORT_SECTION pSection, EEStringData *pStrData)
5016 {        
5017     PEImageLayout *pNativeImage = GetNativeImage();
5018
5019     // Get the table
5020     COUNT_T tableSize;
5021     TADDR tableBase = pNativeImage->GetDirectoryData(&pSection->Section, &tableSize);
5022
5023     // Walk the handle table.
5024     // @TODO: If we ever care about the perf of this function, we could sort the tokens
5025     // using as a key the string they point to, so we could do a binary search
5026     for (SIZE_T * pEntry = (SIZE_T *)tableBase ; pEntry < (SIZE_T *)(tableBase + tableSize); pEntry++)
5027     {
5028         // Ensure that the compiler won't fetch the value twice
5029         SIZE_T entry = VolatileLoadWithoutBarrier(pEntry);
5030
5031         if (CORCOMPILE_IS_POINTER_TAGGED(entry))
5032         {
5033             BYTE * pBlob = (BYTE *) pNativeImage->GetRvaData(CORCOMPILE_UNTAG_TOKEN(entry));
5034
5035             // Note that we only care about strings from current module, and so we do not check ENCODE_MODULE_OVERRIDE
5036             if (*pBlob++ == ENCODE_STRING_HANDLE && 
5037                     TokenFromRid(CorSigUncompressData((PCCOR_SIGNATURE&) pBlob), mdtString) ==  token)
5038             {
5039                 EnsureWritablePages(pEntry);
5040
5041                 // This string hasn't been fixed up. Synchronize the update with the normal
5042                 // fixup logic
5043                 {
5044                     CrstHolder ch(this->GetFixupCrst());
5045
5046                     if (!CORCOMPILE_IS_POINTER_TAGGED(*pEntry))
5047                     {
5048                         // We lost the race, just return current entry
5049                     }
5050                     else
5051                     {
5052                         *pEntry = (SIZE_T) ResolveStringRef(token, pDomain, false);
5053                     }
5054                 }
5055
5056                 return (OBJECTHANDLE) *pEntry;
5057             }
5058         }
5059         else
5060         {
5061             OBJECTREF* pRef = (OBJECTREF*) entry;
5062             _ASSERTE((*pRef)->GetMethodTable() == g_pStringClass);
5063
5064             STRINGREF stringRef = (STRINGREF) *pRef;
5065
5066             // Is this the string we are trying to resolve?
5067             if (pStrData->GetCharCount() == stringRef->GetStringLength() &&
5068                 memcmp((void*)pStrData->GetStringBuffer(),
5069                         (void*) stringRef->GetBuffer(),
5070                         pStrData->GetCharCount()*sizeof(WCHAR)) == 0)
5071             {
5072                 // We found it, so we just have to return this instance
5073                 return (OBJECTHANDLE) entry;
5074             }
5075         }
5076     }
5077     return NULL;
5078 }
5079 #endif // FEATURE_PREJIT
5080
5081 OBJECTHANDLE Module::ResolveStringRef(DWORD token, BaseDomain *pDomain, bool bNeedToSyncWithFixups)
5082 {
5083     CONTRACTL
5084     {
5085         INSTANCE_CHECK;
5086         THROWS;
5087         GC_TRIGGERS;
5088         MODE_ANY;
5089         INJECT_FAULT(COMPlusThrowOM());
5090         PRECONDITION(TypeFromToken(token) == mdtString);
5091     }
5092     CONTRACTL_END;
5093
5094     EEStringData strData;
5095     OBJECTHANDLE string = NULL;
5096
5097 #if !BIGENDIAN 
5098     InitializeStringData(token, &strData, NULL);
5099 #else // !!BIGENDIAN
5100     CQuickBytes qb;
5101     InitializeStringData(token, &strData, &qb);
5102 #endif // !!BIGENDIAN
5103
5104     GCX_COOP();
5105
5106     // We can only do this for native images as they guarantee that resolvestringref will be
5107     // called only once per string from this module. @TODO: We really dont have any way of asserting
5108     // this, which would be nice... (and is needed to guarantee correctness)
5109 #ifdef FEATURE_PREJIT 
5110     if (HasNativeImage() && IsNoStringInterning())
5111     {
5112         if (bNeedToSyncWithFixups)
5113         {
5114             // In an ngen image, it is possible that we get here but not be coming from a fixup,
5115             // (FixupNativeEntry case). In that unfortunate case (ngen partial images, dynamic methods,
5116             // lazy string inits) we will have to troll through the fixup list, and in the case the string is there,
5117             // reuse it, if it's  there but hasn't been fixed up, fix it up now, and in the case it isn't
5118             // there at all, then go to our old style string interning. Going through this code path is
5119             // guaranteed to be slow. If necessary, we can further optimize it by sorting the token table,
5120             // Another way of solving this would be having a token to string table (would require knowing
5121             // all our posible stings in the ngen case (this is possible by looking at the IL))
5122
5123             PEImageLayout * pNativeImage = GetNativeImage();
5124
5125             COUNT_T nSections;
5126             PTR_CORCOMPILE_IMPORT_SECTION pSections = pNativeImage->GetNativeImportSections(&nSections);
5127
5128             for (COUNT_T iSection = 0; iSection < nSections; iSection++)
5129             {
5130                 PTR_CORCOMPILE_IMPORT_SECTION pSection = pSections + iSection;
5131
5132                 if (pSection->Type != CORCOMPILE_IMPORT_TYPE_STRING_HANDLE)
5133                     continue;
5134
5135                 OBJECTHANDLE oh = ResolveStringRefHelper(token, pDomain, pSection, &strData);
5136                 if (oh != NULL)
5137                     return oh;
5138             }
5139
5140             // The string is not in our fixup list, so just intern it old style (using hashtable)
5141             goto INTERN_OLD_STYLE;
5142
5143         }
5144         /* Unfortunately, this assert won't work in some cases of generics, consider the following scenario:
5145
5146             1) Generic type in mscorlib.
5147             2) Instantiation of generic (1) (via valuetype) in another module
5148             3) other module now holds a copy of the code of the generic for that particular instantiation
5149                however, it is resolving the string literals against mscorlib, which breaks the invariant
5150                this assert was based on (no string fixups against other modules). In fact, with NoStringInterning,
5151                our behavior is not very intuitive.
5152         */
5153         /*
5154         _ASSERTE(pDomain == GetAssembly()->GetDomain() && "If your are doing ldstr for a string"
5155         "in another module, either the JIT is very smart or you have a bug, check INLINE_NO_CALLEE_LDSTR");
5156
5157         */
5158         /*
5159         Dev10 804385 bugfix - 
5160            We should be using appdomain that the string token lives in (GetAssembly->GetDomain())
5161            to allocate the System.String object instead of the appdomain that first uses the ldstr <token> (pDomain).
5162
5163            Otherwise, it is possible to get into the situation that pDomain is unloaded but GetAssembly->GetDomain() is 
5164            still kicking around. Anything else that is still using that string will now be pointing to an object 
5165            that will be freed when the next GC happens.
5166         */
5167         pDomain = GetAssembly()->GetDomain();
5168
5169         // The caller is going to update an ngen fixup entry. The fixup entry
5170         // is used to reference the string and to ensure that the string is
5171         // allocated only once. Hence, this operation needs to be done under a lock.
5172         _ASSERTE(GetFixupCrst()->OwnedByCurrentThread());
5173
5174         // Allocate handle
5175         OBJECTREF* pRef = pDomain->AllocateObjRefPtrsInLargeTable(1);
5176
5177         STRINGREF str = AllocateStringObject(&strData);
5178         SetObjectReference(pRef, str, NULL);
5179
5180         #ifdef LOGGING 
5181         int length = strData.GetCharCount();
5182         length = min(length, 100);
5183         WCHAR *szString = (WCHAR *)_alloca((length + 1) * sizeof(WCHAR));
5184         memcpyNoGCRefs((void*)szString, (void*)strData.GetStringBuffer(), length * sizeof(WCHAR));
5185         szString[length] = '\0';
5186         LOG((LF_APPDOMAIN, LL_INFO10000, "String literal \"%S\" won't be interned due to NoInterningAttribute\n", szString));
5187         #endif // LOGGING
5188
5189         return (OBJECTHANDLE) pRef;
5190     }
5191
5192
5193 INTERN_OLD_STYLE:
5194 #endif
5195     // Retrieve the string from the either the appropriate LoaderAllocator
5196     LoaderAllocator *pLoaderAllocator;
5197
5198     if (this->IsCollectible())
5199         pLoaderAllocator = this->GetLoaderAllocator();
5200     else
5201         pLoaderAllocator = pDomain->GetLoaderAllocator();
5202         
5203     string = (OBJECTHANDLE)pLoaderAllocator->GetStringObjRefPtrFromUnicodeString(&strData);
5204
5205     return string;
5206 }
5207 #endif // CROSSGEN_COMPILE
5208
5209 //
5210 // Used by the verifier.  Returns whether this stringref is valid.
5211 //
5212 CHECK Module::CheckStringRef(DWORD token)
5213 {
5214     LIMITED_METHOD_CONTRACT;
5215     CHECK(TypeFromToken(token)==mdtString);
5216     CHECK(!IsNilToken(token));
5217     CHECK(GetMDImport()->IsValidToken(token));
5218     CHECK_OK;
5219 }
5220
5221 mdToken Module::GetEntryPointToken()
5222 {
5223     WRAPPER_NO_CONTRACT;
5224
5225     return m_file->GetEntryPointToken();
5226 }
5227
5228 BYTE *Module::GetProfilerBase()
5229 {
5230     CONTRACT(BYTE*)
5231     {
5232         NOTHROW;
5233         GC_NOTRIGGER;
5234         CANNOT_TAKE_LOCK;
5235     }
5236     CONTRACT_END;
5237
5238     if (m_file == NULL)  // I'd rather assert this is not the case...
5239     {
5240         RETURN NULL;
5241     }
5242     else if (HasNativeImage())
5243     {
5244         RETURN (BYTE*)(GetNativeImage()->GetBase());
5245     }
5246     else if (m_file->IsLoaded())
5247     {
5248         RETURN  (BYTE*)(m_file->GetLoadedIL()->GetBase());
5249     }
5250     else
5251     {
5252         RETURN NULL;
5253     }
5254 }
5255
5256 void Module::AddActiveDependency(Module *pModule, BOOL unconditional)
5257 {
5258     CONTRACT_VOID
5259     {
5260         THROWS;
5261         GC_TRIGGERS;
5262         PRECONDITION(CheckPointer(pModule));
5263         PRECONDITION(pModule != this);
5264         PRECONDITION(!IsSystem());
5265         PRECONDITION(!GetAssembly()->IsDomainNeutral() || pModule->GetAssembly()->IsDomainNeutral() || GetAppDomain()->IsDefaultDomain());
5266         POSTCONDITION(IsSingleAppDomain() || HasActiveDependency(pModule));
5267         POSTCONDITION(IsSingleAppDomain() || !unconditional || HasUnconditionalActiveDependency(pModule));
5268         // Postcondition about activation
5269     }
5270     CONTRACT_END;
5271
5272     // Activation tracking is not require in single domain mode. Activate the target immediately.
5273     if (IsSingleAppDomain())
5274     {
5275         pModule->EnsureActive();
5276         RETURN;
5277     }
5278
5279     // In the default AppDomain we delay a closure walk until a sharing attempt has been made
5280     // This might result in a situation where a domain neutral assembly from the default AppDomain 
5281     // depends on something resolved by assembly resolve event (even Ref.Emit assemblies) 
5282     // Since we won't actually share such assemblies, and the default AD itself cannot go away we 
5283     // do not need to assert for such assemblies, thus " || GetAppDomain()->IsDefaultDomain()"
5284
5285     CONSISTENCY_CHECK_MSG(!GetAssembly()->IsDomainNeutral() || pModule->GetAssembly()->IsDomainNeutral() || GetAppDomain()->IsDefaultDomain(),
5286                           "Active dependency from domain neutral to domain bound is illegal");
5287
5288     // We must track this dependency for multiple domains' use
5289     STRESS_LOG2(LF_CLASSLOADER, LL_INFO100000," %p -> %p\n",this,pModule);
5290
5291     _ASSERTE(!unconditional || pModule->HasNativeImage()); 
5292     _ASSERTE(!unconditional || HasNativeImage()); 
5293
5294     COUNT_T index;
5295
5296     // this function can run in parallel with DomainFile::Activate and sychronizes via GetNumberOfActivations()
5297     // because we expose dependency only in the end Domain::Activate might miss it, but it will increment a counter module
5298     // so we can realize we have to additionally propagate a dependency into that appdomain.
5299     // currently we do it just by rescanning al appdomains.
5300     // needless to say, updating the counter and checking counter+adding dependency to the list should be atomic
5301
5302
5303     BOOL propagate = FALSE;
5304     ULONG startCounter=0;
5305     ULONG endCounter=0;
5306     do
5307     {
5308         // First, add the dependency to the physical dependency list
5309         {
5310 #ifdef _DEBUG 
5311             CHECK check;
5312             if (unconditional)
5313                 check=DomainFile::CheckUnactivatedInAllDomains(this);
5314 #endif // _DEBUG
5315
5316             CrstHolder lock(&m_Crst);
5317             startCounter=GetNumberOfActivations();
5318
5319             index = m_activeDependencies.FindElement(0, pModule);
5320             if (index == (COUNT_T) ArrayList::NOT_FOUND)
5321             {
5322                 propagate = TRUE;
5323                 STRESS_LOG3(LF_CLASSLOADER, LL_INFO100,"Adding new module dependency %p -> %p, unconditional=%i\n",this,pModule,unconditional);
5324             }
5325
5326             if (unconditional)
5327             {
5328                 if (propagate)
5329                 {
5330                     CONSISTENCY_CHECK_MSG(check,
5331                                       "Unconditional dependency cannot be added after module has already been activated");
5332
5333                     index = m_activeDependencies.GetCount();
5334                     m_activeDependencies.Append(pModule);
5335                     m_unconditionalDependencies.SetBit(index);
5336                     STRESS_LOG2(LF_CLASSLOADER, LL_INFO100," Unconditional module dependency propagated %p -> %p\n",this,pModule);
5337                     // Now other threads can skip this dependency without propagating.
5338                 }
5339                 RETURN;
5340             }
5341
5342         }
5343
5344         // Now we have to propagate any module activations in the loader
5345
5346         if (propagate)
5347         {
5348
5349             _ASSERTE(!unconditional);
5350             DomainFile::PropagateNewActivation(this, pModule);
5351
5352             CrstHolder lock(&m_Crst);
5353             STRESS_LOG2(LF_CLASSLOADER, LL_INFO100," Conditional module dependency propagated %p -> %p\n",this,pModule);
5354             // Now other threads can skip this dependency without propagating.
5355             endCounter=GetNumberOfActivations();
5356             if(startCounter==endCounter)
5357                 m_activeDependencies.Append(pModule);
5358         }
5359         
5360     }while(propagate && startCounter!=endCounter); //need to retry if someone was activated in parallel
5361     RETURN;
5362 }
5363
5364 BOOL Module::HasActiveDependency(Module *pModule)
5365 {
5366     CONTRACTL
5367     {
5368         NOTHROW;
5369         GC_NOTRIGGER;
5370         MODE_ANY;
5371         PRECONDITION(CheckPointer(pModule));
5372     }
5373     CONTRACTL_END;
5374
5375     if (pModule == this)
5376         return TRUE;
5377
5378     DependencyIterator i = IterateActiveDependencies();
5379     while (i.Next())
5380     {
5381         if (i.GetDependency() == pModule)
5382             return TRUE;
5383     }
5384
5385     return FALSE;
5386 }
5387
5388 BOOL Module::HasUnconditionalActiveDependency(Module *pModule)
5389 {
5390     CONTRACTL
5391     {
5392         NOTHROW;
5393         CAN_TAKE_LOCK;
5394         MODE_ANY;
5395         PRECONDITION(CheckPointer(pModule));
5396     }
5397     CONTRACTL_END;
5398
5399     if (pModule == this)
5400         return TRUE;
5401
5402     DependencyIterator i = IterateActiveDependencies();
5403     while (i.Next())
5404     {
5405         if (i.GetDependency() == pModule
5406             && i.IsUnconditional())
5407             return TRUE;
5408     }
5409
5410     return FALSE;
5411 }
5412
5413 void Module::EnableModuleFailureTriggers(Module *pModuleTo, AppDomain *pDomain)
5414 {
5415     CONTRACTL
5416     {
5417         THROWS;
5418         GC_TRIGGERS;
5419         MODE_ANY;
5420     }
5421     CONTRACTL_END;
5422     // At this point we need to enable failure triggers we have placed in the code for this module.  However,
5423     // the failure trigger codegen logic is NYI.  To keep correctness, we just allow the exception to propagate
5424     // here.  Note that in general this will enforce the failure invariants, but will also result in some rude
5425     // behavior as these failures will be propagated too widely rather than constrained to the appropriate
5426     // assemblies/app domains.
5427     //
5428     // This should throw.
5429     STRESS_LOG2(LF_CLASSLOADER, LL_INFO100,"EnableModuleFailureTriggers for module %p in AppDomain %i\n",pModuleTo,pDomain->GetId().m_dwId);
5430     DomainFile *pDomainFileTo = pModuleTo->GetDomainFile(pDomain);
5431     pDomainFileTo->EnsureActive();
5432
5433     // @NYI: shouldn't get here yet since we propagate failures
5434     UNREACHABLE_MSG("Module failure triggers NYI");
5435 }
5436
5437 #endif //!DACCESS_COMPILE
5438
5439 //
5440 // an GetAssemblyIfLoadedAppDomainIterator is used to iterate over all domains that
5441 // are known to be walkable at the time GetAssemblyIfLoaded is executed.
5442 //
5443 // The iteration is guaranteed to include all domains that exist at the
5444 // start & end of the iteration that are safely accessible. This class is logically part
5445 // of GetAssemblyIfLoaded and logically has the same set of contracts.
5446 //
5447
5448 class GetAssemblyIfLoadedAppDomainIterator
5449 {
5450     enum IteratorType
5451     {
5452         StackwalkingThreadIterator,
5453         AllAppDomainWalkingIterator,
5454         CurrentAppDomainIterator
5455     }  m_iterType;
5456
5457 public:
5458     GetAssemblyIfLoadedAppDomainIterator() : 
5459       m_adIteratorAll(TRUE),
5460       m_appDomainCurrent(NULL),
5461       m_pFrame(NULL),
5462       m_fNextCalledForCurrentADIterator(FALSE)
5463     {
5464         LIMITED_METHOD_CONTRACT;
5465 #ifndef DACCESS_COMPILE
5466         if (IsStackWalkerThread())
5467         {
5468             Thread * pThread = (Thread *)ClrFlsGetValue(TlsIdx_StackWalkerWalkingThread);
5469             m_iterType = StackwalkingThreadIterator;
5470             m_pFrame = pThread->GetFrame();
5471             m_appDomainCurrent = pThread->GetDomain();
5472         }
5473         else if (IsGCThread())
5474         {
5475             m_iterType = AllAppDomainWalkingIterator;
5476             m_adIteratorAll.Init();
5477         }
5478         else
5479         {
5480             _ASSERTE(::GetAppDomain() != NULL);
5481             m_appDomainCurrent = ::GetAppDomain();
5482             m_iterType = CurrentAppDomainIterator;
5483         }
5484 #else //!DACCESS_COMPILE
5485         // We have to walk all AppDomains in debugger
5486         m_iterType = AllAppDomainWalkingIterator;
5487         m_adIteratorAll.Init();
5488 #endif //!DACCESS_COMPILE
5489     }
5490
5491     BOOL Next()
5492     {
5493         WRAPPER_NO_CONTRACT;
5494
5495         switch (m_iterType)
5496         {
5497 #ifndef DACCESS_COMPILE
5498         case StackwalkingThreadIterator:
5499             if (!m_fNextCalledForCurrentADIterator)
5500             {
5501                 m_fNextCalledForCurrentADIterator = TRUE;
5502
5503                 // Try searching frame chain if the current domain is NULL
5504                 if (m_appDomainCurrent == NULL)
5505                     return Next();
5506
5507                 return TRUE;
5508             }
5509             else
5510             {
5511                 while (m_pFrame != FRAME_TOP)
5512                 {
5513                     AppDomain * pDomain = m_pFrame->GetReturnDomain();
5514                     if ((pDomain != NULL) && (pDomain != m_appDomainCurrent))
5515                     {
5516                         m_appDomainCurrent = pDomain;
5517                         return TRUE;
5518                     }
5519                     m_pFrame = m_pFrame->PtrNextFrame();
5520                 }
5521
5522                 return FALSE;
5523             }
5524 #endif //!DACCESS_COMPILE
5525
5526         case AllAppDomainWalkingIterator:
5527             {
5528                 BOOL fSuccess = m_adIteratorAll.Next();
5529                 if (fSuccess)
5530                     m_appDomainCurrent = m_adIteratorAll.GetDomain();
5531                 return fSuccess;
5532             }
5533
5534 #ifndef DACCESS_COMPILE
5535         case CurrentAppDomainIterator:
5536             {
5537                 BOOL retVal;
5538                 retVal = !m_fNextCalledForCurrentADIterator;
5539                 m_fNextCalledForCurrentADIterator = TRUE;
5540                 return retVal;
5541             }
5542 #endif //!DACCESS_COMPILE
5543         
5544         default:
5545             _ASSERTE(FALSE);
5546             return FALSE;
5547         }
5548     }
5549
5550     AppDomain * GetDomain()
5551     {
5552         LIMITED_METHOD_CONTRACT;
5553
5554         return m_appDomainCurrent;
5555     }
5556
5557     BOOL UsingCurrentAD()
5558     {
5559         LIMITED_METHOD_CONTRACT;
5560         return m_iterType == CurrentAppDomainIterator;
5561     }
5562
5563   private:
5564
5565     UnsafeAppDomainIterator m_adIteratorAll;
5566     AppDomain *             m_appDomainCurrent;
5567     Frame *                 m_pFrame;
5568     BOOL                    m_fNextCalledForCurrentADIterator;
5569 };  // class GetAssemblyIfLoadedAppDomainIterator
5570
5571 #if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5572 // This function, given an AssemblyRef into the ngen generated native metadata section, will find the assembly referenced if
5573 // 1. The Assembly is defined with a different name than the AssemblyRef provides
5574 // 2. The Assembly has reached the stage of being loaded.
5575 // This function is used as a helper function to assist GetAssemblyIfLoaded with its tasks in the conditions
5576 // where GetAssemblyIfLoaded must succeed (or we violate various invariants in the system required for
5577 // correct implementation of GC, Stackwalking, and generic type loading.
5578 Assembly * Module::GetAssemblyIfLoadedFromNativeAssemblyRefWithRefDefMismatch(mdAssemblyRef kAssemblyRef, BOOL *pfDiscoveredAssemblyRefMatchesTargetDefExactly)
5579 {
5580     CONTRACT(Assembly *)
5581     {
5582         INSTANCE_CHECK;
5583         NOTHROW;
5584         GC_NOTRIGGER;
5585         FORBID_FAULT;
5586         MODE_ANY;
5587         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
5588     }
5589     CONTRACT_END;
5590
5591     _ASSERTE(HasNativeImage());
5592
5593     Assembly *pAssembly = NULL;
5594     IMDInternalImport *pImportFoundNativeImage = this->GetNativeAssemblyImport(FALSE);
5595
5596     if (!pImportFoundNativeImage)
5597     {
5598         RETURN NULL;
5599     }
5600
5601     if (kAssemblyRef != mdAssemblyRefNil)
5602     {
5603         // Scan CORCOMPILE_DEPENDENCIES tables
5604         PEImageLayout* pNativeLayout = this->GetNativeImage();
5605         COUNT_T dependencyCount;
5606         CORCOMPILE_DEPENDENCY *pDependencies = pNativeLayout->GetNativeDependencies(&dependencyCount);
5607
5608         // Find the assemblyDef that defines the exact target
5609         mdAssemblyRef foundAssemblyDef = mdAssemblyRefNil;
5610
5611         for (COUNT_T i = 0; i < dependencyCount; ++i)
5612         {
5613             CORCOMPILE_DEPENDENCY* pDependency = &(pDependencies[i]);
5614             if (pDependency->dwAssemblyRef == kAssemblyRef)
5615             {
5616                 foundAssemblyDef = pDependency->dwAssemblyDef;
5617                 break;
5618             }
5619         }
5620
5621         // In this case we know there is no assembly redirection involved. Skip any additional work.
5622         if (kAssemblyRef == foundAssemblyDef)
5623         {
5624             *pfDiscoveredAssemblyRefMatchesTargetDefExactly = true;
5625             RETURN NULL;
5626         }
5627
5628         if (foundAssemblyDef != mdAssemblyRefNil)
5629         {
5630             // Find out if THIS reference is satisfied
5631             // Specify fDoNotUtilizeExtraChecks to prevent recursion
5632             Assembly *pAssemblyCandidate = this->GetAssemblyIfLoaded(foundAssemblyDef, NULL, NULL, pImportFoundNativeImage, TRUE /*fDoNotUtilizeExtraChecks*/); 
5633
5634             // This extended check is designed only to find assemblies loaded via an AssemblySpecBindingCache based binder. Verify that's what we found.
5635             if(pAssemblyCandidate != NULL)
5636             {
5637                 if (!pAssemblyCandidate->GetManifestFile()->HasHostAssembly())
5638                 {
5639                     pAssembly = pAssemblyCandidate;
5640                 }
5641                 else
5642                 {
5643                     DWORD binderFlags = 0;
5644                     ICLRPrivAssembly * pPrivBinder = pAssemblyCandidate->GetManifestFile()->GetHostAssembly();
5645                     HRESULT hrBinderFlagCheck = pPrivBinder->GetBinderFlags(&binderFlags);
5646                     if (SUCCEEDED(hrBinderFlagCheck) && (binderFlags & BINDER_FINDASSEMBLYBYSPEC_REQUIRES_EXACT_MATCH))
5647                     {
5648                         pAssembly = pAssemblyCandidate;
5649                     }
5650                     else
5651                     {
5652                         // This should only happen in the generic instantiation case when multiple threads are racing and
5653                         // the assembly found is one which we will determine is the wrong assembly.
5654                         //
5655                         // 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.
5656                         _ASSERTE("Non-AssemblySpecBindingCache based assembly found with extended search" && !(IsStackWalkerThread() || IsGCThread()) && IsGenericInstantiationLookupCompareThread());
5657                     }
5658                 }
5659             }
5660         }
5661     }
5662
5663     RETURN pAssembly;
5664 }
5665 #endif // !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5666
5667 // Fills ppContainingWinRtAppDomain only if WinRT type name is passed and if the assembly is found (return value != NULL).
5668 Assembly * 
5669 Module::GetAssemblyIfLoaded(
5670     mdAssemblyRef       kAssemblyRef, 
5671     LPCSTR              szWinRtNamespace,   // = NULL
5672     LPCSTR              szWinRtClassName,   // = NULL
5673     IMDInternalImport * pMDImportOverride,  // = NULL
5674     BOOL                fDoNotUtilizeExtraChecks, // = FALSE
5675     ICLRPrivBinder      *pBindingContextForLoadedAssembly // = NULL
5676 )    
5677 {
5678     CONTRACT(Assembly *)
5679     {
5680         INSTANCE_CHECK;
5681         NOTHROW;
5682         GC_NOTRIGGER;
5683         FORBID_FAULT;
5684         MODE_ANY;
5685         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
5686         SUPPORTS_DAC;
5687     }
5688     CONTRACT_END;
5689
5690     Assembly * pAssembly = NULL;
5691     BOOL fCanUseRidMap = ((pMDImportOverride == NULL) &&
5692                           (szWinRtNamespace == NULL));
5693
5694 #ifdef _DEBUG
5695     fCanUseRidMap = fCanUseRidMap && (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GetAssemblyIfLoadedIgnoreRidMap) == 0);
5696 #endif
5697
5698     // 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.
5699 #if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5700     _ASSERTE(!IsGenericInstantiationLookupCompareThread() || HasNativeImage());
5701 #endif
5702
5703     // Don't do a lookup if an override IMDInternalImport is provided, since the lookup is for the
5704     // standard IMDInternalImport and might result in an incorrect result.
5705     // WinRT references also do not update RID map, so don't try to look it up
5706     if (fCanUseRidMap)
5707     {
5708         pAssembly = LookupAssemblyRef(kAssemblyRef);
5709     }
5710     
5711 #ifndef DACCESS_COMPILE
5712     // Check if actually loaded, unless a GC is in progress or the current thread is
5713     // walking the stack (either its own stack, or another thread's stack) as that works
5714     // only with loaded assemblies
5715     //
5716     // NOTE: The case where the current thread is walking a stack can be problematic for
5717     // other reasons, as the remaining code of this function uses "GetAppDomain()", when
5718     // in fact the right AppDomain to use is the one corresponding to the frame being
5719     // traversed on the walked thread. Dev10 TFS bug# 762348 tracks that issue.
5720     if ((pAssembly != NULL) && !IsGCThread() && !IsStackWalkerThread())
5721     {
5722         _ASSERTE(::GetAppDomain() != NULL);
5723         DomainAssembly * pDomainAssembly = pAssembly->FindDomainAssembly(::GetAppDomain());
5724         if ((pDomainAssembly == NULL) || !pDomainAssembly->IsLoaded())
5725             pAssembly = NULL;
5726     }   
5727 #endif //!DACCESS_COMPILE
5728     
5729     if (pAssembly == NULL)
5730     {
5731         // If in stackwalking or gc mode
5732         // For each AppDomain that is on the stack being walked...
5733         // For each AppDomain in the process... if gc'ing
5734         // For the current AppDomain ... if none of the above
5735         GetAssemblyIfLoadedAppDomainIterator appDomainIter;
5736
5737         while (appDomainIter.Next())
5738         {
5739             AppDomain * pAppDomainExamine = appDomainIter.GetDomain();
5740             
5741             DomainAssembly * pCurAssemblyInExamineDomain = GetAssembly()->FindDomainAssembly(pAppDomainExamine);
5742             if (pCurAssemblyInExamineDomain == NULL)
5743             {
5744                 continue;
5745             }
5746
5747 #ifdef FEATURE_COMINTEROP
5748             if (szWinRtNamespace != NULL)
5749             {
5750                 if (IsIntrospectionOnly())
5751                 {   // We do not have to implement this method for ReflectionOnly WinRT type requests
5752                     // ReflectionOnly WinRT types will never have instances on GC heap to be inspected by stackwalking or by debugger
5753                     break;
5754                 }
5755                 
5756                 _ASSERTE(szWinRtClassName != NULL);
5757                 
5758                 CLRPrivBinderWinRT * pWinRtBinder = pAppDomainExamine->GetWinRtBinder();
5759                 if (pWinRtBinder == nullptr)
5760                 {   // We are most likely in AppX mode (calling AppX::IsAppXProcess() for verification is painful in DACCESS)
5761 #ifndef DACCESS_COMPILE
5762                     // Note: We should also look
5763                     // Check designer binding context present (only in AppXDesignMode)
5764                     ICLRPrivBinder * pCurrentBinder = pAppDomainExamine->GetLoadContextHostBinder();
5765                     if (pCurrentBinder != nullptr)
5766                     {   // We have designer binding context, look for the type in it
5767                         ReleaseHolder<ICLRPrivWinRtTypeBinder> pCurrentWinRtTypeBinder;
5768                         HRESULT hr = pCurrentBinder->QueryInterface(__uuidof(ICLRPrivWinRtTypeBinder), (void **)&pCurrentWinRtTypeBinder);
5769                         
5770                         // The binder should be an instance of code:CLRPrivBinderAppX class that implements the interface
5771                         _ASSERTE(SUCCEEDED(hr) && (pCurrentWinRtTypeBinder != nullptr));
5772                         
5773                         if (SUCCEEDED(hr))
5774                         {
5775                             ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
5776                             pAssembly = (Assembly *)pCurrentWinRtTypeBinder->FindAssemblyForWinRtTypeIfLoaded(
5777                                 (void *)pAppDomainExamine, 
5778                                 szWinRtNamespace, 
5779                                 szWinRtClassName);
5780                         }
5781                     }
5782 #endif //!DACCESS_COMPILE
5783                     if (pAssembly == nullptr)
5784                     {   
5785 #if defined(FEATURE_APPX_BINDER)
5786                         // Use WinRT binder from "global" AppX binder (there's only 1 AppDomain in non-design mode)
5787                         CLRPrivBinderAppX * pAppXBinder = CLRPrivBinderAppX::GetBinderOrNull();
5788                         if (pAppXBinder != nullptr)
5789                         {
5790                             pWinRtBinder = pAppXBinder->GetWinRtBinder();
5791                         }
5792 #endif // defined(FEATURE_APPX_BINDER)
5793                     }
5794                 }
5795                 
5796                 if (pWinRtBinder != nullptr)
5797                 {
5798                     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
5799                     pAssembly = pWinRtBinder->FindAssemblyForTypeIfLoaded(
5800                         dac_cast<PTR_AppDomain>(pAppDomainExamine), 
5801                         szWinRtNamespace, 
5802                         szWinRtClassName);
5803                 }
5804                 
5805                 // Never store WinMD AssemblyRefs into the rid map.
5806                 if (pAssembly != NULL)
5807                 {
5808                     break;
5809                 }
5810                 
5811                 // Never attemt to search the assembly spec binding cache for this form of WinRT assembly reference.
5812                 continue;
5813             }
5814 #endif // FEATURE_COMINTEROP
5815
5816 #ifndef DACCESS_COMPILE
5817             {
5818                 IMDInternalImport * pMDImport = (pMDImportOverride == NULL) ? (GetMDImport()) : (pMDImportOverride);
5819                 
5820                 //we have to be very careful here.
5821                 //we are using InitializeSpecInternal so we need to make sure that under no condition 
5822                 //the data we pass to it can outlive the assembly spec.
5823                 AssemblySpec spec;
5824                 if (FAILED(spec.InitializeSpecInternal(kAssemblyRef, 
5825                                                        pMDImport, 
5826                                                        pCurAssemblyInExamineDomain,
5827                                                        IsIntrospectionOnly(), 
5828                                                        FALSE /*fAllowAllocation*/)))
5829                 {
5830                     continue;
5831                 }
5832
5833                 // If we have been passed the binding context for the loaded assembly that is being looked up in the 
5834                 // cache, then set it up in the AssemblySpec for the cache lookup to use it below.
5835                 if (pBindingContextForLoadedAssembly != NULL)
5836                 {
5837                     _ASSERTE(spec.GetBindingContext() == NULL);
5838                     spec.SetBindingContext(pBindingContextForLoadedAssembly);
5839                 }
5840                 DomainAssembly * pDomainAssembly = nullptr;
5841
5842 #ifdef FEATURE_APPX_BINDER
5843                 if (AppX::IsAppXProcess_Initialized_NoFault() && GetAssembly()->GetManifestFile()->HasHostAssembly())
5844                 {
5845                     ICLRPrivAssembly * pPrivBinder = GetAssembly()->GetManifestFile()->GetHostAssembly();
5846                     ReleaseHolder<ICLRPrivAssembly> pPrivAssembly;
5847                     HRESULT hrCachedResult;
5848                     if (SUCCEEDED(pPrivBinder->FindAssemblyBySpec(pAppDomainExamine, &spec, &hrCachedResult, &pPrivAssembly)) &&
5849                         SUCCEEDED(hrCachedResult))
5850                     {
5851                         pDomainAssembly = pAppDomainExamine->FindAssembly(pPrivAssembly);
5852                     }
5853                 }
5854                 else
5855 #endif // FEATURE_APPX_BINDER
5856                 {
5857                     pDomainAssembly = pAppDomainExamine->FindCachedAssembly(&spec, FALSE /*fThrow*/);
5858                 }
5859
5860                 if (pDomainAssembly && pDomainAssembly->IsLoaded())
5861                     pAssembly = pDomainAssembly->GetCurrentAssembly(); // <NOTE> Do not use GetAssembly - that may force the completion of a load
5862
5863                 // Only store in the rid map if working with the current AppDomain.
5864                 if (fCanUseRidMap && pAssembly && appDomainIter.UsingCurrentAD())
5865                     StoreAssemblyRef(kAssemblyRef, pAssembly);
5866
5867                 if (pAssembly != NULL)
5868                     break;
5869             }
5870 #endif //!DACCESS_COMPILE
5871         }
5872     }
5873
5874 #if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5875     if (pAssembly == NULL && (IsStackWalkerThread() || IsGCThread() || IsGenericInstantiationLookupCompareThread()) && !fDoNotUtilizeExtraChecks)
5876     {
5877         // The GetAssemblyIfLoaded function must succeed in finding assemblies which have already been loaded in a series of interesting cases
5878         // (GC, Stackwalking, GenericInstantiationLookup). This logic is used to handle cases where the normal lookup done above
5879         // 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
5880         // run in cases which are not known to be problematic, or would not benefit from the logic here.
5881         //
5882         // 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
5883         // image depends on an assembly through some sort of binding version/public key token adjustment (due to binding policy, unification, or portability rules)
5884         // and the assembly depended on was loaded through a binder that utilizes the AssemblySpecBindingCache for binder caching. (The cache's in the other
5885         // binder's successfully answer the GetAssemblyIfLoaded question in the case of non-exact matches where the match was discovered during
5886         // ngen resolution.)
5887         // This restricts the scenario to a somewhat restricted case.
5888
5889         BOOL eligibleForAdditionalChecks = TRUE;
5890         if (szWinRtNamespace != NULL)
5891             eligibleForAdditionalChecks = FALSE; // WinRT binds do not support this scan
5892 #ifdef FEATURE_FUSION
5893         else if ((this->GetAssembly()->GetManifestFile()->GetLoadContext() != LOADCTX_TYPE_DEFAULT) && (this->GetAssembly()->GetManifestFile()->GetLoadContext() != LOADCTX_TYPE_HOSTED))
5894             eligibleForAdditionalChecks = FALSE; // Only load and hosted context binds support this kind of discovery.
5895 #endif // FEATURE_FUSION
5896         else if (this->GetAssembly()->GetManifestFile()->IsDesignerBindingContext())
5897         {
5898             eligibleForAdditionalChecks = FALSE; 
5899             // 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.
5900             // 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)
5901             // A more correct version of this check would probably allow assemblies loaded into the shared designer binding context to be eligibleForAdditionalChecks; however
5902             // 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
5903             // 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
5904             // there is customer need for a fix.
5905         }
5906         else if (IsIntrospectionOnly())
5907             eligibleForAdditionalChecks = FALSE;
5908
5909         AssemblySpec specSearchAssemblyRef;
5910
5911         // Get the assembly ref information that we are attempting to satisfy.
5912         if (eligibleForAdditionalChecks)
5913         {
5914             IMDInternalImport * pMDImport = (pMDImportOverride == NULL) ? (GetMDImport()) : (pMDImportOverride);
5915
5916             if (FAILED(specSearchAssemblyRef.InitializeSpecInternal(kAssemblyRef, 
5917                                                     pMDImport, 
5918                                                     NULL,
5919                                                     FALSE, 
5920                                                     FALSE /*fAllowAllocation*/)))
5921             {
5922                 eligibleForAdditionalChecks = FALSE; // If an assemblySpec can't be constructed then we're not going to succeed
5923                                                      // This should not ever happen, due to the above checks, but this logic 
5924                                                      // is intended to be defensive against unexpected behavior.
5925             }
5926             else if (specSearchAssemblyRef.IsContentType_WindowsRuntime())
5927             {
5928                 eligibleForAdditionalChecks = FALSE; // WinRT binds do not support this scan
5929             }
5930         }
5931
5932         if (eligibleForAdditionalChecks)
5933         {
5934             BOOL abortAdditionalChecks = false;
5935
5936             // When working with an ngenn'd assembly, as an optimization we can scan only that module for dependency info.
5937             bool onlyScanCurrentModule = HasNativeImage() && GetFile()->IsAssembly();
5938             mdAssemblyRef foundAssemblyRef = mdAssemblyRefNil;
5939
5940             GetAssemblyIfLoadedAppDomainIterator appDomainIter;
5941
5942             // In each AppDomain that might be interesting, scan for an ngen image that is loaded that has a dependency on the same 
5943             // assembly that is now being looked up. If that ngen image has the same dependency, then we can use the CORCOMPILE_DEPENDENCIES
5944             // table to find the exact AssemblyDef that defines the assembly, and attempt a load based on that information.
5945             // As this logic is expected to be used only in exceedingly rare situations, this code has not been tuned for performance
5946             // in any way.
5947             while (!abortAdditionalChecks && appDomainIter.Next())
5948             {
5949                 AppDomain * pAppDomainExamine = appDomainIter.GetDomain();
5950             
5951                 DomainAssembly * pCurAssemblyInExamineDomain = GetAssembly()->FindDomainAssembly(pAppDomainExamine);
5952                 if (pCurAssemblyInExamineDomain == NULL)
5953                 {
5954                     continue;
5955                 }
5956
5957                 DomainFile *pDomainFileNativeImage;
5958                 
5959                 if (onlyScanCurrentModule)
5960                 {
5961                     pDomainFileNativeImage = pCurAssemblyInExamineDomain;
5962                     // Do not reset foundAssemblyRef.
5963                     // This will allow us to avoid scanning for foundAssemblyRef in each domain we iterate through
5964                 }
5965                 else
5966                 {
5967                     foundAssemblyRef = mdAssemblyRefNil;
5968                     pDomainFileNativeImage = pAppDomainExamine->GetDomainFilesWithNativeImagesList();
5969                 }
5970
5971                 while (!abortAdditionalChecks && (pDomainFileNativeImage != NULL) && (pAssembly == NULL))
5972                 {
5973                     Module *pNativeImageModule = pDomainFileNativeImage->GetCurrentModule();
5974                     _ASSERTE(pNativeImageModule->HasNativeImage());
5975                     IMDInternalImport *pImportFoundNativeImage = pNativeImageModule->GetNativeAssemblyImport(FALSE);
5976                     if (pImportFoundNativeImage != NULL)
5977                     {
5978                         if (IsNilToken(foundAssemblyRef))
5979                         {
5980                             // Enumerate assembly refs in nmd space, and compare against held ref.
5981                             HENUMInternalHolder hAssemblyRefEnum(pImportFoundNativeImage);
5982                             if (FAILED(hAssemblyRefEnum.EnumInitNoThrow(mdtAssemblyRef, mdAssemblyRefNil)))
5983                             {
5984                                 continue;
5985                             }
5986
5987                             mdAssemblyRef assemblyRef = mdAssemblyRefNil;
5988
5989                             // Find if the native image has a matching assembly ref in its compile dependencies.
5990                             while (pImportFoundNativeImage->EnumNext(&hAssemblyRefEnum, &assemblyRef) && (pAssembly == NULL))
5991                             {
5992                                 AssemblySpec specFoundAssemblyRef;
5993                                 if (FAILED(specFoundAssemblyRef.InitializeSpecInternal(assemblyRef, 
5994                                                                         pImportFoundNativeImage, 
5995                                                                         NULL,
5996                                                                         FALSE, 
5997                                                                         FALSE /*fAllowAllocation*/)))
5998                                 {
5999                                     continue; // If the spec cannot be loaded, it isn't the one we're looking for
6000                                 }
6001
6002                                 // Check for AssemblyRef equality
6003                                 if (specSearchAssemblyRef.CompareEx(&specFoundAssemblyRef))
6004                                 {
6005                                     foundAssemblyRef = assemblyRef;
6006                                     break;
6007                                 }
6008                             }
6009                         }
6010
6011                         pAssembly = pNativeImageModule->GetAssemblyIfLoadedFromNativeAssemblyRefWithRefDefMismatch(foundAssemblyRef, &abortAdditionalChecks);
6012
6013                         if (fCanUseRidMap && pAssembly && appDomainIter.UsingCurrentAD())
6014                             StoreAssemblyRef(kAssemblyRef, pAssembly);
6015                     }
6016
6017                     // If we're only scanning one module for accurate dependency information, break the loop here.
6018                     if (onlyScanCurrentModule)
6019                         break;
6020
6021                     pDomainFileNativeImage = pDomainFileNativeImage->FindNextDomainFileWithNativeImage();
6022                 }
6023             }
6024         }
6025     }
6026 #endif // !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
6027
6028     // When walking the stack or computing GC information this function should never fail.
6029     _ASSERTE((pAssembly != NULL) || !(IsStackWalkerThread() || IsGCThread()));
6030
6031 #ifdef DACCESS_COMPILE
6032     
6033     // Note: In rare cases when debugger walks the stack, we could actually have pAssembly=NULL here.
6034     // To fix that we should DACize the AppDomain-iteration code above (especially AssemblySpec).
6035     _ASSERTE(pAssembly != NULL);
6036     
6037 #endif //DACCESS_COMPILE
6038     
6039     RETURN pAssembly;
6040 } // Module::GetAssemblyIfLoaded
6041
6042 DWORD 
6043 Module::GetAssemblyRefFlags(
6044     mdAssemblyRef tkAssemblyRef)
6045 {
6046     CONTRACTL
6047     {
6048         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
6049         GC_NOTRIGGER;
6050         MODE_ANY;
6051     }
6052     CONTRACTL_END;
6053     
6054     _ASSERTE(TypeFromToken(tkAssemblyRef) == mdtAssemblyRef);
6055     
6056     LPCSTR      pszAssemblyName;
6057     const void *pbPublicKeyOrToken;
6058     DWORD cbPublicKeyOrToken;
6059
6060     DWORD dwAssemblyRefFlags;
6061     IfFailThrow(GetMDImport()->GetAssemblyRefProps(
6062             tkAssemblyRef, 
6063             &pbPublicKeyOrToken, 
6064             &cbPublicKeyOrToken, 
6065             &pszAssemblyName, 
6066             NULL, 
6067             NULL, 
6068             NULL, 
6069             &dwAssemblyRefFlags));
6070     
6071     return dwAssemblyRefFlags;
6072 } // Module::GetAssemblyRefFlags
6073
6074 #ifndef DACCESS_COMPILE 
6075
6076 // Arguments:
6077 //   szWinRtTypeNamespace ... Namespace of WinRT type.
6078 //   szWinRtTypeClassName ... Name of WinRT type, NULL for non-WinRT (classic) types.
6079 DomainAssembly * Module::LoadAssembly(
6080     AppDomain *   pDomain, 
6081     mdAssemblyRef kAssemblyRef, 
6082     LPCUTF8       szWinRtTypeNamespace, 
6083     LPCUTF8       szWinRtTypeClassName)
6084 {
6085     CONTRACT(DomainAssembly *)
6086     {
6087         INSTANCE_CHECK;
6088         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
6089         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
6090         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM();); }
6091         MODE_ANY;
6092         PRECONDITION(CheckPointer(pDomain));
6093         POSTCONDITION(CheckPointer(RETVAL, NULL_NOT_OK));
6094         //POSTCONDITION((CheckPointer(GetAssemblyIfLoaded(kAssemblyRef, szWinRtTypeNamespace, szWinRtTypeClassName)), NULL_NOT_OK));
6095     }
6096     CONTRACT_END;
6097
6098     ETWOnStartup (LoaderCatchCall_V1, LoaderCatchCallEnd_V1);
6099
6100     DomainAssembly * pDomainAssembly;
6101
6102     //
6103     // Early out quickly if the result is cached
6104     //
6105     Assembly * pAssembly = LookupAssemblyRef(kAssemblyRef);
6106     if (pAssembly != NULL)
6107     {
6108         _ASSERTE(HasBindableIdentity(kAssemblyRef));
6109
6110         pDomainAssembly = pAssembly->FindDomainAssembly(pDomain);
6111
6112         if (pDomainAssembly == NULL)
6113             pDomainAssembly = pAssembly->GetDomainAssembly(pDomain);
6114         pDomain->LoadDomainFile(pDomainAssembly, FILE_LOADED);
6115
6116         RETURN pDomainAssembly;
6117     }
6118
6119     bool fHasBindableIdentity = HasBindableIdentity(kAssemblyRef);
6120     
6121 #ifdef FEATURE_REFLECTION_ONLY_LOAD
6122     if (IsIntrospectionOnly())
6123     {
6124         // We will not get here on GC thread
6125         GCX_PREEMP();
6126         
6127         AssemblySpec spec;
6128         spec.InitializeSpec(kAssemblyRef, GetMDImport(), GetDomainFile(GetAppDomain())->GetDomainAssembly(), IsIntrospectionOnly());
6129         if (szWinRtTypeClassName != NULL)
6130         {
6131             spec.SetWindowsRuntimeType(szWinRtTypeNamespace, szWinRtTypeClassName);
6132         }
6133         pDomainAssembly = GetAppDomain()->BindAssemblySpecForIntrospectionDependencies(&spec);
6134     }
6135     else
6136 #endif //FEATURE_REFLECTION_ONLY_LOAD
6137     {
6138         PEAssemblyHolder pFile = GetDomainFile(GetAppDomain())->GetFile()->LoadAssembly(
6139                 kAssemblyRef, 
6140                 NULL, 
6141                 szWinRtTypeNamespace, 
6142                 szWinRtTypeClassName);
6143         AssemblySpec spec;
6144         spec.InitializeSpec(kAssemblyRef, GetMDImport(), GetDomainFile(GetAppDomain())->GetDomainAssembly(), IsIntrospectionOnly());
6145         // Set the binding context in the AssemblySpec if one is available. This can happen if the LoadAssembly ended up
6146         // invoking the custom AssemblyLoadContext implementation that returned a reference to an assembly bound to a different
6147         // AssemblyLoadContext implementation.
6148         ICLRPrivBinder *pBindingContext = pFile->GetBindingContext();
6149         if (pBindingContext != NULL)
6150         {
6151             spec.SetBindingContext(pBindingContext);
6152         }
6153         if (szWinRtTypeClassName != NULL)
6154         {
6155             spec.SetWindowsRuntimeType(szWinRtTypeNamespace, szWinRtTypeClassName);
6156         }
6157         pDomainAssembly = GetAppDomain()->LoadDomainAssembly(&spec, pFile, FILE_LOADED, NULL);
6158     }
6159
6160     if (pDomainAssembly != NULL)
6161     {
6162         _ASSERTE(
6163             IsIntrospectionOnly() ||                        // GetAssemblyIfLoaded will not find introspection-only assemblies
6164             !fHasBindableIdentity ||                        // GetAssemblyIfLoaded will not find non-bindable assemblies
6165             pDomainAssembly->IsSystem() ||                  // GetAssemblyIfLoaded will not find mscorlib (see AppDomain::FindCachedFile)
6166             !pDomainAssembly->IsLoaded() ||                 // GetAssemblyIfLoaded will not find not-yet-loaded assemblies
6167             GetAssemblyIfLoaded(kAssemblyRef, NULL, NULL, NULL, FALSE, pDomainAssembly->GetFile()->GetHostAssembly()) != NULL);     // GetAssemblyIfLoaded should find all remaining cases
6168
6169         // Note: We cannot cache WinRT AssemblyRef, because it is meaningless without the TypeRef context
6170         if (pDomainAssembly->GetCurrentAssembly() != NULL)
6171         {
6172             if (fHasBindableIdentity)
6173             {
6174                 StoreAssemblyRef(kAssemblyRef, pDomainAssembly->GetCurrentAssembly());
6175             }
6176         }
6177     }
6178
6179     RETURN pDomainAssembly;
6180 }
6181
6182 #endif // !DACCESS_COMPILE
6183
6184 Module *Module::GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL permitResources)
6185 {
6186     CONTRACT(Module *)
6187     {
6188         INSTANCE_CHECK;
6189         NOTHROW;
6190         GC_NOTRIGGER;
6191         MODE_ANY;
6192         PRECONDITION(TypeFromToken(kFile) == mdtFile
6193                      || TypeFromToken(kFile) == mdtModuleRef);
6194         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
6195         FORBID_FAULT;
6196         SUPPORTS_DAC;
6197     }
6198     CONTRACT_END;
6199
6200     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
6201
6202     // Handle the module ref case
6203     if (TypeFromToken(kFile) == mdtModuleRef)
6204     {
6205         LPCSTR moduleName;
6206         if (FAILED(GetMDImport()->GetModuleRefProps(kFile, &moduleName)))
6207         {
6208             RETURN NULL;
6209         }
6210         
6211         // This is required only because of some lower casing on the name
6212         kFile = GetAssembly()->GetManifestFileToken(moduleName);
6213         if (kFile == mdTokenNil)
6214             RETURN NULL;
6215         
6216         RETURN GetAssembly()->GetManifestModule()->GetModuleIfLoaded(kFile, onlyLoadedInAppDomain, permitResources);
6217     }
6218     
6219     Module *pModule = LookupFile(kFile);
6220     if (pModule == NULL)
6221     {
6222         if (IsManifest())
6223         {
6224             if (kFile == mdFileNil)
6225                 pModule = GetAssembly()->GetManifestModule();
6226         }
6227         else
6228         {
6229             // If we didn't find it there, look at the "master rid map" in the manifest file
6230             Assembly *pAssembly = GetAssembly();
6231             mdFile kMatch;
6232             
6233             // This is required only because of some lower casing on the name
6234             kMatch = pAssembly->GetManifestFileToken(GetMDImport(), kFile);
6235             if (IsNilToken(kMatch))
6236             {
6237                 if (kMatch == mdFileNil)
6238                 {
6239                     pModule = pAssembly->GetManifestModule();
6240                 }
6241                 else
6242                 {
6243                     RETURN NULL;
6244                 }
6245             }
6246             else
6247             pModule = pAssembly->GetManifestModule()->LookupFile(kMatch);
6248         }
6249         
6250 #ifndef DACCESS_COMPILE
6251         if (pModule != NULL)
6252             StoreFileNoThrow(kFile, pModule);
6253 #endif
6254     }
6255     
6256     // We may not want to return a resource module
6257     if (!permitResources && pModule && pModule->IsResource())
6258         pModule = NULL;
6259
6260 #ifndef DACCESS_COMPILE
6261 #if defined(FEATURE_MULTIMODULE_ASSEMBLIES)
6262     // check if actually loaded, unless happens during GC (GC works only with loaded assemblies)
6263     if (!GCHeapUtilities::IsGCInProgress() && onlyLoadedInAppDomain && pModule && !pModule->IsManifest())
6264     {
6265         DomainModule *pDomainModule = pModule->FindDomainModule(GetAppDomain());
6266         if (pDomainModule == NULL || !pDomainModule->IsLoaded())
6267             pModule = NULL;
6268     }    
6269 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
6270 #endif // !DACCESS_COMPILE
6271     RETURN pModule;
6272 }
6273
6274 #ifndef DACCESS_COMPILE
6275
6276 DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile,
6277                                BOOL permitResources/*=TRUE*/, BOOL bindOnly/*=FALSE*/)
6278 {
6279     CONTRACT(DomainFile *)
6280     {
6281         INSTANCE_CHECK;
6282         THROWS;
6283         GC_TRIGGERS;
6284         MODE_ANY;
6285         PRECONDITION(TypeFromToken(kFile) == mdtFile
6286                      || TypeFromToken(kFile) == mdtModuleRef);
6287         POSTCONDITION(CheckPointer(RETVAL, !permitResources || bindOnly ? NULL_OK : NULL_NOT_OK));
6288     }
6289     CONTRACT_END;
6290
6291 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
6292
6293     // Handle the module ref case
6294     if (TypeFromToken(kFile) == mdtModuleRef)
6295     {
6296         LPCSTR moduleName;
6297         IfFailThrow(GetMDImport()->GetModuleRefProps(kFile, &moduleName));
6298         
6299         mdFile kFileLocal = GetAssembly()->GetManifestFileToken(moduleName);
6300         
6301         if (kFileLocal == mdTokenNil)
6302         {
6303             COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
6304         }
6305         
6306         RETURN GetAssembly()->GetManifestModule()->LoadModule(pDomain, kFileLocal, permitResources, bindOnly);
6307     }
6308
6309     // First, make sure the assembly is loaded in our domain
6310
6311     DomainAssembly *pDomainAssembly = GetAssembly()->FindDomainAssembly(pDomain);
6312     if (!bindOnly)
6313     {
6314         if (pDomainAssembly == NULL)
6315             pDomainAssembly = GetAssembly()->GetDomainAssembly(pDomain);
6316         pDomain->LoadDomainFile(pDomainAssembly, FILE_LOADED);
6317     }
6318
6319     if (kFile == mdFileNil)
6320         RETURN pDomainAssembly;
6321
6322     if (pDomainAssembly == NULL)
6323         RETURN NULL;
6324
6325     // Now look for the module in the rid maps
6326
6327     Module *pModule = LookupFile(kFile);
6328     if (pModule == NULL && !IsManifest())
6329     {
6330         // If we didn't find it there, look at the "master rid map" in the manifest file
6331         Assembly *pAssembly = GetAssembly();
6332         mdFile kMatch = pAssembly->GetManifestFileToken(GetMDImport(), kFile);
6333         if (IsNilToken(kMatch)) {
6334             if (kMatch == mdFileNil)
6335                 pModule = pAssembly->GetManifestModule();
6336             else
6337                 COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
6338         }
6339         else
6340             pModule = pAssembly->GetManifestModule()->LookupFile(kMatch);
6341     }
6342
6343     // Get a DomainModule for our domain
6344
6345     DomainModule *pDomainModule = NULL;
6346     if (pModule)
6347     {
6348         pDomainModule = pModule->FindDomainModule(pDomain);
6349
6350         if (!bindOnly && (permitResources || !pModule->IsResource()))
6351         {
6352             if (pDomainModule == NULL)
6353                 pDomainModule = pDomain->LoadDomainModule(pDomainAssembly, (PEModule*) pModule->GetFile(), FILE_LOADED);
6354             else
6355                 pDomain->LoadDomainFile(pDomainModule, FILE_LOADED);
6356         }
6357     }
6358     else if (!bindOnly)
6359     {
6360         PEModuleHolder pFile(GetAssembly()->LoadModule_AddRef(kFile, permitResources));
6361         if (pFile)
6362             pDomainModule = pDomain->LoadDomainModule(pDomainAssembly, pFile, FILE_LOADED);
6363     }
6364     
6365     if (pDomainModule != NULL && pDomainModule->GetCurrentModule() != NULL)
6366     {
6367         // Make sure the module we're loading isn't its own assembly
6368         if (pDomainModule->GetCurrentModule()->IsManifest())
6369             COMPlusThrowHR(COR_E_ASSEMBLY_NOT_EXPECTED);
6370         
6371         // Cache the result in the rid map
6372         StoreFileThrowing(kFile, pDomainModule->GetCurrentModule());
6373     }
6374     
6375     // Make sure we didn't load a different module than what was in the rid map
6376     CONSISTENCY_CHECK(pDomainModule == NULL || pModule == NULL || pDomainModule->GetModule() == pModule);
6377
6378     // We may not want to return a resource module
6379     if (!permitResources && pDomainModule != NULL && pDomainModule->GetFile()->IsResource())
6380         pDomainModule = NULL;
6381
6382     RETURN pDomainModule;
6383 #else //!FEATURE_MULTIMODULE_ASSEMBLIES
6384     if (bindOnly)
6385     {
6386         RETURN  NULL;
6387     }
6388     else
6389     {
6390         LPCSTR psModuleName=NULL;
6391         if (TypeFromToken(kFile) == mdtModuleRef)
6392         {
6393             // This is a moduleRef
6394             IfFailThrow(GetMDImport()->GetModuleRefProps(kFile, &psModuleName));
6395         }
6396         else
6397         {
6398            // This is mdtFile
6399            IfFailThrow(GetAssembly()->GetManifestImport()->GetFileProps(kFile,
6400                                       &psModuleName,
6401                                       NULL,
6402                                       NULL,
6403                                       NULL));
6404         }
6405         SString name(SString::Utf8, psModuleName);
6406         EEFileLoadException::Throw(name, COR_E_MULTIMODULEASSEMBLIESDIALLOWED, NULL);
6407     }
6408 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
6409 }
6410 #endif // !DACCESS_COMPILE
6411
6412 PTR_Module Module::LookupModule(mdToken kFile,BOOL permitResources/*=TRUE*/)
6413 {
6414     CONTRACT(PTR_Module)
6415     {
6416         INSTANCE_CHECK;
6417         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
6418         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
6419         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; 
6420         else { INJECT_FAULT(COMPlusThrowOM()); }
6421         MODE_ANY;
6422         PRECONDITION(TypeFromToken(kFile) == mdtFile
6423                      || TypeFromToken(kFile) == mdtModuleRef);
6424         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
6425         SUPPORTS_DAC;
6426     }
6427     CONTRACT_END;
6428     
6429     if (TypeFromToken(kFile) == mdtModuleRef)
6430     {
6431         LPCSTR moduleName;
6432         IfFailThrow(GetMDImport()->GetModuleRefProps(kFile, &moduleName));
6433         mdFile kFileLocal = GetAssembly()->GetManifestFileToken(moduleName);
6434
6435         if (kFileLocal == mdTokenNil)
6436             COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
6437
6438         RETURN GetAssembly()->GetManifestModule()->LookupModule(kFileLocal, permitResources);
6439     }
6440
6441     PTR_Module pModule = LookupFile(kFile);
6442     if (pModule == NULL && !IsManifest())
6443     {
6444         // If we didn't find it there, look at the "master rid map" in the manifest file
6445         Assembly *pAssembly = GetAssembly();
6446         mdFile kMatch = pAssembly->GetManifestFileToken(GetMDImport(), kFile);
6447         if (IsNilToken(kMatch)) {
6448             if (kMatch == mdFileNil)
6449                 pModule = pAssembly->GetManifestModule();
6450             else
6451             COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
6452         }
6453         else
6454             pModule = pAssembly->GetManifestModule()->LookupFile(kMatch);
6455     }
6456     RETURN pModule;
6457 }
6458
6459
6460 TypeHandle Module::LookupTypeRef(mdTypeRef token)
6461 {
6462     STATIC_CONTRACT_NOTHROW;
6463     STATIC_CONTRACT_GC_NOTRIGGER;
6464     STATIC_CONTRACT_FORBID_FAULT;
6465     SUPPORTS_DAC;
6466
6467     _ASSERTE(TypeFromToken(token) == mdtTypeRef);
6468
6469     g_IBCLogger.LogRidMapAccess( MakePair( this, token ) );
6470
6471     TypeHandle entry = TypeHandle::FromTAddr(dac_cast<TADDR>(m_TypeRefToMethodTableMap.GetElement(RidFromToken(token))));
6472
6473     if (entry.IsNull())
6474         return TypeHandle();
6475
6476     // Cannot do this in a NOTHROW function.
6477     // Note that this could be called while doing GC from the prestub of
6478     // a method to resolve typerefs in a signature. We cannot THROW
6479     // during GC.
6480
6481     // @PERF: Enable this so that we do not need to touch metadata
6482     // to resolve typerefs
6483
6484 #ifdef FIXUPS_ALL_TYPEREFS 
6485
6486     if (CORCOMPILE_IS_POINTER_TAGGED((SIZE_T) entry.AsPtr()))
6487     {
6488 #ifndef DACCESS_COMPILE 
6489         Module::RestoreTypeHandlePointer(&entry, TRUE);
6490         m_TypeRefToMethodTableMap.SetElement(RidFromToken(token), dac_cast<PTR_TypeRef>(value.AsTAddr()));
6491 #else // DACCESS_COMPILE
6492         DacNotImpl();
6493 #endif // DACCESS_COMPILE
6494     }
6495
6496 #endif // FIXUPS_ALL_TYPEREFS
6497
6498     return entry;
6499 }
6500
6501 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
6502 mdTypeRef Module::LookupTypeRefByMethodTable(MethodTable *pMT)
6503 {
6504     STANDARD_VM_CONTRACT;
6505
6506     HENUMInternalHolder hEnumTypeRefs(GetMDImport());
6507     mdTypeRef token;
6508     hEnumTypeRefs.EnumAllInit(mdtTypeRef);
6509     while (hEnumTypeRefs.EnumNext(&token))
6510     {
6511         TypeHandle thRef = LookupTypeRef(token);
6512         if (thRef.IsNull() || thRef.IsTypeDesc())
6513         {
6514             continue;
6515         }
6516
6517         MethodTable *pMTRef = thRef.AsMethodTable();
6518         if (pMT->HasSameTypeDefAs(pMTRef))
6519         {
6520             _ASSERTE(pMTRef->IsTypicalTypeDefinition());
6521             return token;
6522         }
6523     }
6524
6525 #ifdef FEATURE_READYTORUN_COMPILER
6526     if (IsReadyToRunCompilation())
6527     {
6528         if (pMT->GetClass()->IsEquivalentType())
6529         {
6530             GetSvcLogger()->Log(W("ReadyToRun: Type reference to equivalent type cannot be encoded\n"));
6531             ThrowHR(E_NOTIMPL);
6532         }
6533
6534         // FUTURE: Encoding of new cross-module references for ReadyToRun
6535         // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise.
6536         // GetSvcLogger()->Log(W("ReadyToRun: Type reference outside of current version bubble cannot be encoded\n"));
6537     }
6538     else
6539 #endif // FEATURE_READYTORUN_COMPILER
6540     {
6541         // FUTURE TODO: Version resilience
6542         _ASSERTE(!"Cross module type reference not found");
6543     }
6544     ThrowHR(E_FAIL);
6545 }
6546
6547 mdMemberRef Module::LookupMemberRefByMethodDesc(MethodDesc *pMD)
6548 {
6549     STANDARD_VM_CONTRACT;
6550
6551     HENUMInternalHolder hEnumMemberRefs(GetMDImport());
6552     mdMemberRef token;
6553     hEnumMemberRefs.EnumAllInit(mdtMemberRef);
6554     while (hEnumMemberRefs.EnumNext(&token))
6555     {
6556         BOOL fIsMethod = FALSE;
6557         TADDR addr = LookupMemberRef(token, &fIsMethod);
6558         if (fIsMethod)
6559         {
6560             MethodDesc *pCurMD = dac_cast<PTR_MethodDesc>(addr);
6561             if (pCurMD == pMD)
6562             {
6563                 return token;
6564             }
6565         }
6566     }
6567
6568     // FUTURE TODO: Version resilience
6569     _ASSERTE(!"Cross module method reference not found");
6570     ThrowHR(E_FAIL);
6571 }
6572 #endif // FEATURE_NATIVE_IMAGE_GENERATION
6573
6574 #ifndef DACCESS_COMPILE 
6575
6576 //
6577 // Increase the size of one of the maps, such that it can handle a RID of at least "rid".
6578 //
6579 // This function must also check that another thread didn't already add a LookupMap capable
6580 // of containing the same RID.
6581 //
6582 PTR_TADDR LookupMapBase::GrowMap(Module * pModule, DWORD rid)
6583 {
6584     CONTRACT(PTR_TADDR)
6585     {
6586         INSTANCE_CHECK;
6587         THROWS;
6588         GC_NOTRIGGER;
6589         MODE_ANY;
6590         INJECT_FAULT(ThrowOutOfMemory(););
6591         POSTCONDITION(CheckPointer(RETVAL));
6592     }
6593     CONTRACT_END;
6594
6595     LookupMapBase *pMap = this;
6596     LookupMapBase *pPrev = NULL;
6597     LookupMapBase *pNewMap = NULL;
6598
6599     // Initial block size
6600     DWORD dwIndex = rid;
6601     DWORD dwBlockSize = 16;
6602
6603     {
6604         CrstHolder ch(pModule->GetLookupTableCrst());
6605         // Check whether we can already handle this RID index
6606         do
6607         {
6608             if (dwIndex < pMap->dwCount)
6609             {
6610                 // Already there - some other thread must have added it
6611                 RETURN pMap->GetIndexPtr(dwIndex);
6612             }
6613
6614             dwBlockSize *= 2;
6615
6616             dwIndex -= pMap->dwCount;
6617
6618             pPrev = pMap;
6619             pMap = pMap->pNext;
6620         } while (pMap != NULL);
6621
6622         _ASSERTE(pPrev != NULL); // should never happen, because there's always at least one map
6623
6624         DWORD dwSizeToAllocate = max(dwIndex + 1, dwBlockSize);
6625
6626         pNewMap = (LookupMapBase *) (void*)pModule->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(LookupMapBase)) + S_SIZE_T(dwSizeToAllocate)*S_SIZE_T(sizeof(TADDR)));
6627
6628         // Note: Memory allocated on loader heap is zero filled
6629         // memset(pNewMap, 0, sizeof(LookupMap) + dwSizeToAllocate*sizeof(void*));
6630
6631         pNewMap->pNext          = NULL;
6632         pNewMap->dwCount        = dwSizeToAllocate;
6633
6634         pNewMap->pTable         = dac_cast<ArrayDPTR(TADDR)>(pNewMap + 1);
6635
6636         // Link ourselves in
6637         VolatileStore<LookupMapBase*>(&(pPrev->pNext), pNewMap);
6638     }
6639
6640     RETURN pNewMap->GetIndexPtr(dwIndex);
6641 }
6642
6643 #endif // DACCESS_COMPILE
6644
6645 PTR_TADDR LookupMapBase::GetElementPtr(DWORD rid)
6646 {
6647     CONTRACTL
6648     {
6649         INSTANCE_CHECK;
6650         NOTHROW;
6651         GC_NOTRIGGER;
6652         MODE_ANY;
6653         SO_TOLERANT;
6654         SUPPORTS_DAC;
6655     }
6656     CONTRACTL_END;
6657
6658     LookupMapBase * pMap = this;
6659
6660 #ifdef FEATURE_PREJIT 
6661     if (pMap->dwNumHotItems > 0)
6662     {
6663 #ifdef _DEBUG_IMPL 
6664         static  DWORD counter = 0;
6665         counter++;
6666         if (counter >= pMap->dwNumHotItems)
6667         {
6668             CheckConsistentHotItemList();
6669             counter = 0;
6670         }
6671 #endif // _DEBUG_IMPL
6672
6673         PTR_TADDR pHotItemValue = pMap->FindHotItemValuePtr(rid);
6674         if (pHotItemValue)
6675         {
6676             return pHotItemValue;
6677         }
6678     }
6679 #endif // FEATURE_PREJIT
6680
6681     DWORD dwIndex = rid;
6682     do
6683     {
6684         if (dwIndex < pMap->dwCount)
6685         {
6686             return pMap->GetIndexPtr(dwIndex);
6687         }
6688
6689         dwIndex -= pMap->dwCount;
6690         pMap = pMap->pNext;
6691     } while (pMap != NULL);
6692
6693     return NULL;
6694 }
6695
6696
6697 #ifdef FEATURE_PREJIT 
6698
6699 // This method can only be called on a compressed map (MapIsCompressed() == true). Compressed rid maps store
6700 // the array of values as packed deltas (each value is based on the accumulated of all the previous entries).
6701 // So this method takes the bit stream of compressed data we're navigating and the value of the last entry
6702 // retrieved allowing us to calculate the full value of the next entry. Note that the values passed in and out
6703 // here aren't the final values the top-level caller sees. In order to avoid having to touch the compressed
6704 // data on image base relocations we actually store a form of RVA (though relative to the map base rather than
6705 // the module base).
6706 INT32 LookupMapBase::GetNextCompressedEntry(BitStreamReader *pTableStream, INT32 iLastValue)
6707 {
6708     CONTRACTL
6709     {
6710         INSTANCE_CHECK;
6711         NOTHROW;
6712         GC_NOTRIGGER;
6713         MODE_ANY;
6714         SO_TOLERANT;
6715         SUPPORTS_DAC;
6716         PRECONDITION(MapIsCompressed());
6717     }
6718     CONTRACTL_END;
6719
6720     // The next kLookupMapLengthBits bits in the stream are an index into a per-map table that tells us the
6721     // length of the encoded delta.
6722     DWORD dwValueLength = rgEncodingLengths[pTableStream->Read(kLookupMapLengthBits)];
6723
6724     // Then follows a single bit that indicates whether the delta should be added (1) or subtracted (0) from
6725     // the previous entry value to recover the current entry value.
6726     // Once we've read that bit we read the delta (encoded as an unsigned integer using the number of bits
6727     // that we read from the encoding lengths table above).
6728     if (pTableStream->ReadOneFast())
6729         return iLastValue + (INT32)(pTableStream->Read(dwValueLength));
6730     else
6731         return iLastValue - (INT32)(pTableStream->Read(dwValueLength));
6732 }
6733
6734 // This method can only be called on a compressed map (MapIsCompressed() == true). Retrieves the final value
6735 // (e.g. MethodTable*, MethodDesc* etc. based on map type) given the rid of the entry.
6736 TADDR LookupMapBase::GetValueFromCompressedMap(DWORD rid)
6737 {
6738     CONTRACTL
6739     {
6740         INSTANCE_CHECK;
6741         NOTHROW;
6742         GC_NOTRIGGER;
6743         MODE_ANY;
6744         SO_TOLERANT;
6745         SUPPORTS_DAC;
6746         PRECONDITION(MapIsCompressed());
6747     }
6748     CONTRACTL_END;
6749
6750     // Normally to extract the nth entry in the table we have to linearly parse all (n - 1) preceding entries
6751     // (since entries are stored as the delta from the previous entry). Obviously this can yield exceptionally
6752     // poor performance for the later entries in large tables. So we also build an index of the compressed
6753     // stream. This index has an entry for every kLookupMapIndexStride entries in the compressed table. Each
6754     // index entry contains the full RVA (relative to the map) of the corresponding table entry plus the bit
6755     // offset in the stream from which to start parsing the next entry's data.
6756     // In this fashion we can get to within kLookupMapIndexStride entries of our target entry and then decode
6757     // our way to the final target.
6758
6759     // Ensure that index does not go beyond end of the saved table
6760     if (rid >= dwCount)
6761         return 0;
6762
6763     // Calculate the nearest entry in the index that is lower than our target index in the full table.
6764     DWORD dwIndexEntry = rid / kLookupMapIndexStride;
6765
6766     // Then calculate how many additional entries we'll need to decode from the compressed streams to recover
6767     // the target entry.
6768     DWORD dwSubIndex = rid % kLookupMapIndexStride;
6769
6770     // Open a bit stream reader on the index and skip all the entries prior to the one we're interested in.
6771     BitStreamReader sIndexStream(pIndex);
6772     sIndexStream.Skip(dwIndexEntry * cIndexEntryBits);
6773
6774     // The first kBitsPerRVA of the index entry contain the RVA of the corresponding entry in the compressed
6775     // table. If this is exactly the entry we want (dwSubIndex == 0) then we can use this RVA to recover the
6776     // value the caller wants. Our RVAs are based on the map address rather than the module base (simply
6777     // because we don't record the module base in LookupMapBase). A delta of zero encodes a null value,
6778     // otherwise we simply add the RVA to the our map address to recover the full pointer.
6779     // Note that most LookupMaps are embedded structures (in Module) so we can't directly dac_cast<TADDR> our
6780     // "this" pointer for DAC builds. Instead we have to use the slightly slower (in DAC) but more flexible
6781     // PTR_HOST_INT_TO_TADDR() which copes with interior host pointers.
6782     INT32 iValue = (INT32)sIndexStream.Read(kBitsPerRVA);
6783     if (dwSubIndex == 0)
6784         return iValue ? PTR_HOST_INT_TO_TADDR(this) + iValue : 0;
6785
6786     // Otherwise we must parse one or more entries in the compressed table to accumulate more deltas to the
6787     // base RVA we read above. The remaining portion of the index entry has the bit offset into the compressed
6788     // table at which to begin parsing.
6789     BitStreamReader sTableStream(dac_cast<PTR_CBYTE>(pTable));
6790     sTableStream.Skip(sIndexStream.Read(cIndexEntryBits - kBitsPerRVA));
6791
6792     // Parse all the entries up to our target entry. Each step takes the RVA from the previous cycle (or from
6793     // the index entry we read above) and applies the compressed delta of the next table entry to it.
6794     for (DWORD i = 0; i < dwSubIndex; i++)
6795         iValue = GetNextCompressedEntry(&sTableStream, iValue);
6796
6797     // We have the final RVA so recover the actual pointer from it (a zero RVA encodes a NULL pointer). Note
6798     // the use of PTR_HOST_INT_TO_TADDR() rather than dac_cast<TADDR>, see previous comment on
6799     // PTR_HOST_INT_TO_TADDR for an explanation.
6800     return iValue ? PTR_HOST_INT_TO_TADDR(this) + iValue : 0;
6801 }
6802
6803 PTR_TADDR LookupMapBase::FindHotItemValuePtr(DWORD rid)
6804 {
6805     LIMITED_METHOD_DAC_CONTRACT;
6806
6807     if  (dwNumHotItems < 5)
6808     {
6809         // do simple linear search if there are only a few hot items
6810         for (DWORD i = 0; i < dwNumHotItems; i++)
6811         {
6812             if (hotItemList[i].rid == rid)
6813                 return dac_cast<PTR_TADDR>(
6814                     dac_cast<TADDR>(hotItemList) + i * sizeof(HotItem) + offsetof(HotItem, value));
6815         }
6816     }
6817     else
6818     {
6819         // otherwise do binary search
6820         if (hotItemList[0].rid <= rid && rid <= hotItemList[dwNumHotItems-1].rid)
6821         {
6822             DWORD l = 0;
6823             DWORD r = dwNumHotItems;
6824             while (l + 1 < r)
6825             {
6826                 // loop invariant:
6827                 _ASSERTE(hotItemList[l].rid <= rid && (r >= dwNumHotItems || rid < hotItemList[r].rid));
6828
6829                 DWORD m = (l + r)/2;
6830                 // loop condition implies l < m < r, hence interval shrinks every iteration, hence loop terminates
6831                 _ASSERTE(l < m && m < r);
6832                 if (rid < hotItemList[m].rid)
6833                     r = m;
6834                 else
6835                     l = m;
6836             }
6837             // now we know l + 1 == r && hotItemList[l].rid <= rid < hotItemList[r].rid
6838             // loop invariant:
6839             _ASSERTE(hotItemList[l].rid <= rid && (r >= dwNumHotItems || rid < hotItemList[r].rid));
6840             if (hotItemList[l].rid == rid)
6841                 return dac_cast<PTR_TADDR>(
6842                     dac_cast<TADDR>(hotItemList) + l * sizeof(HotItem) + offsetof(HotItem, value));
6843         }
6844     }
6845     return NULL;
6846 }
6847
6848 #ifdef _DEBUG 
6849 void LookupMapBase::CheckConsistentHotItemList()
6850 {
6851     LIMITED_METHOD_DAC_CONTRACT;
6852
6853     for (DWORD i = 0; i < dwNumHotItems; i++)
6854     {
6855         DWORD rid = hotItemList[i].rid;
6856
6857         PTR_TADDR pHotValue = dac_cast<PTR_TADDR>(
6858             dac_cast<TADDR>(hotItemList) + i * sizeof(HotItem) + offsetof(HotItem, value));
6859         TADDR hotValue = RelativePointer<TADDR>::GetValueMaybeNullAtPtr(dac_cast<TADDR>(pHotValue));
6860
6861         TADDR value;
6862         if (MapIsCompressed())
6863         {
6864             value = GetValueFromCompressedMap(rid);
6865         }
6866         else
6867         {
6868             PTR_TADDR pValue = GetIndexPtr(rid);
6869             value = RelativePointer<TADDR>::GetValueMaybeNullAtPtr(dac_cast<TADDR>(pValue));
6870         }
6871
6872         _ASSERTE(hotValue == value || value == NULL);
6873     }
6874 }
6875 #endif // _DEBUG
6876
6877 #endif // FEATURE_PREJIT
6878
6879 // Get number of RIDs that this table can store
6880 DWORD LookupMapBase::GetSize()
6881 {
6882     CONTRACTL
6883     {
6884         INSTANCE_CHECK;
6885         NOTHROW;
6886         GC_NOTRIGGER;
6887         MODE_ANY;
6888         SUPPORTS_DAC;
6889     }
6890     CONTRACTL_END;
6891
6892     LookupMapBase * pMap = this;
6893     DWORD dwSize = 0;
6894     do
6895     {
6896         dwSize += pMap->dwCount;
6897         pMap = pMap->pNext;
6898     } while (pMap != NULL);
6899
6900     return dwSize;
6901 }
6902
6903 #ifndef DACCESS_COMPILE
6904
6905 #ifdef _DEBUG 
6906 void LookupMapBase::DebugGetRidMapOccupancy(DWORD *pdwOccupied, DWORD *pdwSize)
6907 {
6908     LIMITED_METHOD_CONTRACT;
6909
6910     *pdwOccupied = 0;
6911     *pdwSize     = 0;
6912
6913     LookupMapBase * pMap = this;
6914
6915     // Go through each linked block
6916     for (; pMap != NULL; pMap = pMap->pNext)
6917     {
6918         DWORD dwIterCount = pMap->dwCount;
6919
6920         for (DWORD i = 0; i < dwIterCount; i++)
6921         {
6922 #ifdef FEATURE_PREJIT
6923             if (pMap->MapIsCompressed())
6924             {
6925                 if (pMap->GetValueFromCompressedMap(i))
6926                     (*pdwOccupied)++;
6927             }
6928             else
6929 #endif // FEATURE_PREJIT
6930             if (pMap->pTable[i] != NULL)
6931                 (*pdwOccupied)++;
6932         }
6933
6934         (*pdwSize) += dwIterCount;
6935     }
6936 }
6937
6938 void Module::DebugLogRidMapOccupancy()
6939 {
6940     WRAPPER_NO_CONTRACT;
6941
6942 #define COMPUTE_RID_MAP_OCCUPANCY(var_suffix, map)                                        \
6943     DWORD dwOccupied##var_suffix, dwSize##var_suffix, dwPercent##var_suffix;              \
6944     map.DebugGetRidMapOccupancy(&dwOccupied##var_suffix, &dwSize##var_suffix);            \
6945     dwPercent##var_suffix = dwOccupied##var_suffix ? ((dwOccupied##var_suffix * 100) / dwSize##var_suffix) : 0;
6946
6947     COMPUTE_RID_MAP_OCCUPANCY(1, m_TypeDefToMethodTableMap);
6948     COMPUTE_RID_MAP_OCCUPANCY(2, m_TypeRefToMethodTableMap);
6949     COMPUTE_RID_MAP_OCCUPANCY(3, m_MethodDefToDescMap);
6950     COMPUTE_RID_MAP_OCCUPANCY(4, m_FieldDefToDescMap);
6951     COMPUTE_RID_MAP_OCCUPANCY(5, m_GenericParamToDescMap);
6952     COMPUTE_RID_MAP_OCCUPANCY(6, m_GenericTypeDefToCanonMethodTableMap);
6953     COMPUTE_RID_MAP_OCCUPANCY(7, m_FileReferencesMap);
6954     COMPUTE_RID_MAP_OCCUPANCY(8, m_ManifestModuleReferencesMap);
6955     COMPUTE_RID_MAP_OCCUPANCY(9, m_MethodDefToPropertyInfoMap);
6956
6957     LOG((
6958         LF_EEMEM,
6959         INFO3,
6960         "   Map occupancy:\n"
6961         "      TypeDefToMethodTable map: %4d/%4d (%2d %%)\n"
6962         "      TypeRefToMethodTable map: %4d/%4d (%2d %%)\n"
6963         "      MethodDefToDesc map:  %4d/%4d (%2d %%)\n"
6964         "      FieldDefToDesc map:  %4d/%4d (%2d %%)\n"
6965         "      GenericParamToDesc map:  %4d/%4d (%2d %%)\n"
6966         "      GenericTypeDefToCanonMethodTable map:  %4d/%4d (%2d %%)\n"
6967         "      FileReferences map:  %4d/%4d (%2d %%)\n"
6968         "      AssemblyReferences map:  %4d/%4d (%2d %%)\n"
6969         "      MethodDefToPropInfo map: %4d/%4d (%2d %%)\n"
6970         ,
6971         dwOccupied1, dwSize1, dwPercent1,
6972         dwOccupied2, dwSize2, dwPercent2,
6973         dwOccupied3, dwSize3, dwPercent3,
6974         dwOccupied4, dwSize4, dwPercent4,
6975         dwOccupied5, dwSize5, dwPercent5,
6976         dwOccupied6, dwSize6, dwPercent6,
6977         dwOccupied7, dwSize7, dwPercent7,
6978         dwOccupied8, dwSize8, dwPercent8,
6979         dwOccupied9, dwSize9, dwPercent9
6980     ));
6981
6982 #undef COMPUTE_RID_MAP_OCCUPANCY
6983 }
6984 #endif // _DEBUG
6985
6986 BOOL Module::CanExecuteCode()
6987 {
6988     WRAPPER_NO_CONTRACT;
6989
6990 #ifdef FEATURE_PREJIT 
6991     // In a passive domain, we lock down which assemblies can run code
6992     if (!GetAppDomain()->IsPassiveDomain())
6993         return TRUE;
6994
6995     Assembly * pAssembly = GetAssembly();
6996     PEAssembly * pPEAssembly = pAssembly->GetManifestFile();
6997
6998     // Only mscorlib is allowed to execute code in an ngen passive domain
6999     if (IsCompilationProcess())
7000         return pPEAssembly->IsSystem();
7001
7002     // ExecuteDLLForAttach does not run the managed entry point in 
7003     // a passive domain to avoid loader-lock deadlocks.
7004     // Hence, it is not safe to execute any code from this assembly.
7005     if (pPEAssembly->GetEntryPointToken(INDEBUG(TRUE)) != mdTokenNil)
7006         return FALSE;
7007
7008     // EXEs loaded using LoadAssembly() may not be loaded at their
7009     // preferred base address. If they have any relocs, these may
7010     // not have been fixed up.
7011     if (!pPEAssembly->IsDll() && !pPEAssembly->IsILOnly())
7012         return FALSE;
7013
7014     // If the assembly does not have FullTrust, we should not execute its code.
7015     if (!pAssembly->GetSecurityDescriptor()->IsFullyTrusted())
7016         return FALSE;
7017 #endif // FEATURE_PREJIT
7018
7019     return TRUE;
7020 }
7021
7022 //
7023 // FindMethod finds a MethodDesc for a global function methoddef or ref
7024 //
7025
7026 MethodDesc *Module::FindMethodThrowing(mdToken pMethod)
7027 {
7028     CONTRACT (MethodDesc *)
7029     {
7030         INSTANCE_CHECK;
7031         THROWS;
7032         GC_TRIGGERS;
7033         MODE_ANY;
7034         POSTCONDITION(CheckPointer(RETVAL));
7035     }
7036     CONTRACT_END
7037
7038     SigTypeContext typeContext;  /* empty type context: methods will not be generic */
7039     RETURN MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(this, pMethod,
7040                                                                &typeContext,
7041                                                                TRUE, /* strictMetadataChecks */
7042                                                                FALSE /* dont get code shared between generic instantiations */);
7043 }
7044
7045 //
7046 // FindMethod finds a MethodDesc for a global function methoddef or ref
7047 //
7048
7049 MethodDesc *Module::FindMethod(mdToken pMethod)
7050 {
7051     CONTRACT (MethodDesc *) {
7052         INSTANCE_CHECK;
7053         NOTHROW;
7054         GC_TRIGGERS;
7055         MODE_ANY;
7056         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
7057     } CONTRACT_END;
7058
7059     MethodDesc *pMDRet = NULL;
7060
7061     EX_TRY
7062     {
7063         pMDRet = FindMethodThrowing(pMethod);
7064     }
7065     EX_CATCH
7066     {
7067 #ifdef _DEBUG 
7068         CONTRACT_VIOLATION(ThrowsViolation);
7069         char szMethodName [MAX_CLASSNAME_LENGTH];
7070         CEEInfo::findNameOfToken(this, pMethod, szMethodName, COUNTOF (szMethodName));
7071         LOG((LF_IJW, LL_INFO10, "Failed to find Method: %s for Vtable Fixup\n", szMethodName));
7072 #endif // _DEBUG
7073     }
7074     EX_END_CATCH(SwallowAllExceptions)
7075
7076     RETURN pMDRet;
7077 }
7078
7079 //
7080 // PopulatePropertyInfoMap precomputes property information during NGen
7081 // that is expensive to look up from metadata at runtime.
7082 //
7083
7084 void Module::PopulatePropertyInfoMap()
7085 {
7086     CONTRACTL
7087     {
7088         INSTANCE_CHECK;
7089         THROWS;
7090         GC_NOTRIGGER;
7091         MODE_ANY;
7092         PRECONDITION(IsCompilationProcess());
7093     }
7094     CONTRACTL_END;
7095
7096     IMDInternalImport* mdImport = GetMDImport();
7097     HENUMInternalHolder   hEnum(mdImport);
7098     hEnum.EnumAllInit(mdtMethodDef);
7099
7100     mdMethodDef md;
7101     while (hEnum.EnumNext(&md))
7102     {
7103         mdProperty prop = 0;
7104         ULONG semantic = 0;
7105         if (mdImport->GetPropertyInfoForMethodDef(md, &prop, NULL, &semantic) == S_OK)
7106         {
7107             // Store the Rid in the lower 24 bits and the semantic in the upper 8
7108             _ASSERTE((semantic & 0xFFFFFF00) == 0);
7109             SIZE_T value = RidFromToken(prop) | (semantic << 24);
7110
7111             // We need to make sure a value of zero indicates an empty LookupMap entry
7112             // Fortunately the semantic will prevent value from being zero
7113             _ASSERTE(value != 0);
7114
7115             m_MethodDefToPropertyInfoMap.AddElement(this, RidFromToken(md), value);
7116         }
7117     }
7118     FastInterlockOr(&m_dwPersistedFlags, COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP);
7119 }
7120
7121 //
7122 // GetPropertyInfoForMethodDef wraps the metadata function of the same name,
7123 // first trying to use the information stored in m_MethodDefToPropertyInfoMap.
7124 //
7125
7126 HRESULT Module::GetPropertyInfoForMethodDef(mdMethodDef md, mdProperty *ppd, LPCSTR *pName, ULONG *pSemantic)
7127 {
7128     CONTRACTL
7129     {
7130         INSTANCE_CHECK;
7131         NOTHROW;
7132         GC_NOTRIGGER;
7133         MODE_ANY;
7134         SO_TOLERANT;
7135     }
7136     CONTRACTL_END;
7137     
7138     HRESULT hr;
7139     
7140     if ((m_dwPersistedFlags & COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP) != 0)
7141     {
7142         SIZE_T value = m_MethodDefToPropertyInfoMap.GetElement(RidFromToken(md));
7143         if (value == 0)
7144         {
7145             _ASSERTE(GetMDImport()->GetPropertyInfoForMethodDef(md, ppd, pName, pSemantic) == S_FALSE);
7146             return S_FALSE;
7147         }
7148         else
7149         {
7150             // Decode the value into semantic and mdProperty as described in PopulatePropertyInfoMap
7151             ULONG semantic = (value & 0xFF000000) >> 24;
7152             mdProperty prop = TokenFromRid(value & 0x00FFFFFF, mdtProperty);
7153
7154 #ifdef _DEBUG
7155             mdProperty dbgPd;
7156             LPCSTR dbgName;
7157             ULONG dbgSemantic;
7158             _ASSERTE(GetMDImport()->GetPropertyInfoForMethodDef(md, &dbgPd, &dbgName, &dbgSemantic) == S_OK);
7159 #endif
7160
7161             if (ppd != NULL)
7162             {
7163                 *ppd = prop;
7164                 _ASSERTE(*ppd == dbgPd);
7165             }
7166             
7167             if (pSemantic != NULL)
7168             {
7169                 *pSemantic = semantic;
7170                 _ASSERTE(*pSemantic == dbgSemantic);
7171             }
7172             
7173             if (pName != NULL)
7174             {
7175                 IfFailRet(GetMDImport()->GetPropertyProps(prop, pName, NULL, NULL, NULL));
7176                 
7177 #ifdef _DEBUG
7178                 HRESULT hr = GetMDImport()->GetPropertyProps(prop, pName, NULL, NULL, NULL);
7179                 _ASSERTE(hr == S_OK);
7180                 _ASSERTE(strcmp(*pName, dbgName) == 0);
7181 #endif
7182             }
7183             
7184             return S_OK;
7185         }
7186     }
7187     
7188     return GetMDImport()->GetPropertyInfoForMethodDef(md, ppd, pName, pSemantic);
7189 }
7190
7191 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
7192 // Fill the m_propertyNameSet hash filter with data that represents every
7193 // property and its name in the module.
7194 void Module::PrecomputeMatchingProperties(DataImage *image)
7195 {
7196     CONTRACTL
7197     {
7198         STANDARD_VM_CHECK;
7199         PRECONDITION(IsCompilationProcess());
7200     }
7201     CONTRACTL_END;
7202
7203     IMDInternalImport* mdImport = GetMDImport();
7204
7205     m_nPropertyNameSet = mdImport->GetCountWithTokenKind(mdtProperty);
7206
7207     if (m_nPropertyNameSet == 0)
7208     {
7209         return;
7210     }
7211     
7212     m_propertyNameSet = new (image->GetHeap()) BYTE[m_nPropertyNameSet];
7213
7214     DWORD nEnumeratedProperties = 0;
7215
7216     HENUMInternalHolder   hEnumTypes(mdImport);
7217     hEnumTypes.EnumAllInit(mdtTypeDef);
7218
7219     // Enumerate all properties of all types
7220     mdTypeDef tkType;
7221     while (hEnumTypes.EnumNext(&tkType))
7222     {
7223         HENUMInternalHolder   hEnumPropertiesForType(mdImport);
7224         hEnumPropertiesForType.EnumInit(mdtProperty, tkType);
7225
7226         mdProperty tkProperty;
7227         while (hEnumPropertiesForType.EnumNext(&tkProperty))
7228         {
7229             LPCSTR name;
7230             HRESULT hr = GetMDImport()->GetPropertyProps(tkProperty, &name, NULL, NULL, NULL);
7231             IfFailThrow(hr);
7232
7233             ++nEnumeratedProperties;
7234
7235             // Use a case-insensitive hash so that we can use this value for
7236             // both case-sensitive and case-insensitive name lookups
7237             SString ssName(SString::Utf8Literal, name);
7238             ULONG nameHashValue = ssName.HashCaseInsensitive();
7239
7240             // Set one bit in m_propertyNameSet per iteration
7241             // This will allow lookup to ensure that the bit from each iteration is set
7242             // and if any are not set, know that the (tkProperty,name) pair is not valid
7243             for (DWORD i = 0; i < NUM_PROPERTY_SET_HASHES; ++i)
7244             {
7245                 DWORD currentHashValue = HashThreeToOne(tkProperty, nameHashValue, i);
7246                 DWORD bitPos = currentHashValue % (m_nPropertyNameSet * 8);
7247                 m_propertyNameSet[bitPos / 8] |= (1 << bitPos % 8);
7248             }
7249         }
7250     }
7251
7252     _ASSERTE(nEnumeratedProperties == m_nPropertyNameSet);
7253 }
7254 #endif // FEATURE_NATIVE_IMAGE_GENERATION
7255
7256 // Check whether the module might possibly have a property with a name with
7257 // the passed hash value without accessing the property's name.  This is done
7258 // by consulting a hash filter populated at NGen time.
7259 BOOL Module::MightContainMatchingProperty(mdProperty tkProperty, ULONG nameHash)
7260 {
7261     CONTRACTL
7262     {
7263         NOTHROW;
7264         GC_NOTRIGGER;
7265         SO_TOLERANT;
7266         MODE_ANY;
7267     }
7268     CONTRACTL_END;
7269
7270     if (m_propertyNameSet)
7271     {
7272         _ASSERTE(HasNativeImage());
7273
7274         // if this property was added after the name set was computed, conservatively
7275         // assume we might have it. This is known to occur in scenarios where a profiler
7276         // injects additional metadata at module load time for an NGEN'ed module. In the
7277         // future other dynamic additions to the module might produce a similar result.
7278         if (RidFromToken(tkProperty) > m_nPropertyNameSet)
7279             return TRUE;
7280
7281         // Check one bit per iteration, failing if any are not set
7282         // We know that all will have been set for any valid (tkProperty,name) pair
7283         for (DWORD i = 0; i < NUM_PROPERTY_SET_HASHES; ++i)
7284         {
7285             DWORD currentHashValue = HashThreeToOne(tkProperty, nameHash, i);
7286             DWORD bitPos = currentHashValue % (m_nPropertyNameSet * 8);
7287             if ((m_propertyNameSet[bitPos / 8] & (1 << bitPos % 8)) == 0)
7288             {
7289                 return FALSE;
7290             }
7291         }
7292     }
7293
7294     return TRUE;
7295 }
7296
7297 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
7298 // Ensure that all elements and flags that we want persisted in the LookupMaps are present
7299 void Module::FinalizeLookupMapsPreSave(DataImage *image)
7300 {
7301     CONTRACTL
7302     {
7303         STANDARD_VM_CHECK;
7304         PRECONDITION(IsCompilationProcess());
7305     }
7306     CONTRACTL_END;
7307
7308     // For each typedef, if it does not need a restore, add the ZAPPED_TYPE_NEEDS_NO_RESTORE flag
7309     {
7310         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
7311
7312         while (typeDefIter.Next())
7313         {
7314             MethodTable * pMT = typeDefIter.GetElement();
7315
7316             if (pMT != NULL && !pMT->NeedsRestore(image))
7317             {
7318                 m_TypeDefToMethodTableMap.AddFlag(RidFromToken(pMT->GetCl()), ZAPPED_TYPE_NEEDS_NO_RESTORE);
7319             }
7320         }
7321     }
7322
7323     // 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
7324     {
7325         LookupMap<PTR_MethodTable>::Iterator genericTypeDefIter(&m_GenericTypeDefToCanonMethodTableMap);
7326
7327         while (genericTypeDefIter.Next())
7328         {
7329             MethodTable * pMT = genericTypeDefIter.GetElement();
7330
7331             if (pMT != NULL && !pMT->NeedsRestore(image))
7332             {
7333                 m_GenericTypeDefToCanonMethodTableMap.AddFlag(RidFromToken(pMT->GetCl()), ZAPPED_GENERIC_TYPE_NEEDS_NO_RESTORE);
7334             }
7335         }
7336     }
7337
7338 }
7339 #endif // FEATURE_NATIVE_IMAGE_GENERATION
7340
7341 // Return true if this module has any live (jitted) JMC functions.
7342 // If a module has no jitted JMC functions, then it's as if it's a
7343 // non-user module.
7344 bool Module::HasAnyJMCFunctions()
7345 {
7346     LIMITED_METHOD_CONTRACT;
7347
7348     // If we have any live JMC funcs in us, then we're a JMC module.
7349     // We count JMC functions when we either explicitly toggle their status
7350     // or when we get the code:DebuggerMethodInfo for them (which happens in a jit-complete).
7351     // Since we don't get the jit-completes for ngen modules, we also check the module's
7352     // "default" status. This means we may err on the side of believing we have
7353     // JMC methods.
7354     return ((m_debuggerSpecificData.m_cTotalJMCFuncs > 0) || m_debuggerSpecificData.m_fDefaultJMCStatus);
7355 }
7356
7357 // Alter our module's count of JMC functions.
7358 // Since these may be called on multiple threads (say 2 threads are jitting
7359 // methods within a module), make it thread safe.
7360 void Module::IncJMCFuncCount()
7361 {
7362     LIMITED_METHOD_CONTRACT;
7363
7364     InterlockedIncrement(&m_debuggerSpecificData.m_cTotalJMCFuncs);
7365 }
7366
7367 void Module::DecJMCFuncCount()
7368 {
7369     LIMITED_METHOD_CONTRACT;
7370
7371     InterlockedDecrement(&m_debuggerSpecificData.m_cTotalJMCFuncs);
7372 }
7373
7374 // code:DebuggerMethodInfo are lazily created. Let them lookup what the default is.
7375 bool Module::GetJMCStatus()
7376 {
7377     LIMITED_METHOD_CONTRACT;
7378
7379     return m_debuggerSpecificData.m_fDefaultJMCStatus;
7380 }
7381
7382 // Set the default JMC status of this module.
7383 void Module::SetJMCStatus(bool fStatus)
7384 {
7385     LIMITED_METHOD_CONTRACT;
7386
7387     m_debuggerSpecificData.m_fDefaultJMCStatus = fStatus;
7388 }
7389
7390 // Update the dynamic metadata if needed. Nop for non-dynamic modules
7391 void Module::UpdateDynamicMetadataIfNeeded()
7392 {
7393     CONTRACTL
7394     {
7395         NOTHROW;
7396         GC_TRIGGERS;
7397     }
7398     CONTRACTL_END;
7399
7400     // Only need to serializing metadata for dynamic modules. For non-dynamic modules, metadata is already available.
7401     if (!IsReflection())
7402     {
7403         return;
7404     }
7405
7406     // Since serializing metadata to an auxillary buffer is only needed by the debugger,
7407     // we should only be doing this for modules that the debugger can see. 
7408     if (!IsVisibleToDebugger())
7409     {
7410         return;
7411     }
7412
7413     
7414     HRESULT hr = S_OK;
7415     EX_TRY
7416     {
7417         GetReflectionModule()->CaptureModuleMetaDataToMemory();
7418     }
7419     EX_CATCH_HRESULT(hr);
7420     
7421     // This Metadata buffer is only used for the debugger, so it's a non-fatal exception for regular CLR execution.
7422     // Just swallow it and keep going. However, with the exception of out-of-memory, we do expect it to
7423     // succeed, so assert on failures.
7424     if (hr != E_OUTOFMEMORY)
7425     {
7426         SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
7427     }
7428
7429 }
7430
7431 #ifdef DEBUGGING_SUPPORTED 
7432
7433 #ifdef FEATURE_FUSION
7434
7435 // Fetch Pdbs from the host
7436 // 
7437 // Returns:
7438 //    No explicit return value. 
7439 //    Caches the pdb stream on the module instance if available.
7440 //    Does nothing if not hosted or if the host does not provide a stream.
7441 //    Throws on exception if the host does provide a stream, but we can't copy it out. 
7442 //    
7443 // Notes:
7444 //    This fetches PDBs from the host and caches them so that they are available for when the debugger attaches.
7445 //    This lets Arrowhead tools run against Whidbey hosts in a compatibility mode.
7446 //    We expect to add a hosting knob that will allow a host to disable this eager fetching and not run in
7447 //    compat mode.
7448 void Module::FetchPdbsFromHost()
7449 {
7450     CONTRACTL
7451     {
7452         THROWS;
7453         GC_TRIGGERS;
7454         MODE_ANY;
7455     }
7456     CONTRACTL_END;
7457
7458     HRESULT hr;
7459     
7460     ReleaseHolder<IStream> pHostStream;
7461
7462     hr = GetHostPdbStream(&pHostStream); // addrefs, holder will release
7463     if (pHostStream == NULL)
7464     {
7465         // Common failure case, we're either not hosted, or the host doesn't have a stream.
7466         return;
7467     }
7468     // pHostStream is a stream implemented by the host, so be extra cautious about methods failing,
7469     // especially with E_NOTIMPL.
7470
7471     SafeComHolder<CGrowableStream> pStream(new CGrowableStream()); // throws
7472
7473     //
7474     // Copy from pHostStream (owned by host) to CGrowableStream (owned by CLR, and visible to debugger from OOP).
7475     // 
7476     
7477     // Get number of bytes to copy.
7478     STATSTG     SizeData = {0};
7479     hr = pHostStream->Stat(&SizeData, STATFLAG_NONAME);
7480     IfFailThrow(hr);
7481     ULARGE_INTEGER streamSize = SizeData.cbSize;
7482
7483     if (streamSize.u.HighPart > 0)
7484     {
7485         // Too big. We shouldn't have a PDB larger than 4gb. 
7486         ThrowHR(E_OUTOFMEMORY);
7487     }
7488     ULONG cbRequest = streamSize.u.LowPart;
7489
7490
7491     // Allocate 
7492     hr = pStream->SetSize(streamSize);
7493     IfFailThrow(hr);
7494
7495     _ASSERTE(pStream->GetRawBuffer().Size() == cbRequest);
7496
7497     // Do the actual copy
7498     ULONG cbActualRead = 0;
7499     hr = pHostStream->Read(pStream->GetRawBuffer().StartAddress(), cbRequest, &cbActualRead);
7500     IfFailThrow(hr);
7501     if (cbRequest != cbActualRead)
7502     {
7503         ThrowWin32(ERROR_READ_FAULT);
7504     }
7505
7506     // We now have a full copy of the PDB provided from the host. 
7507     // This addrefs pStream, which lets it survive past the holder's scope.
7508     SetInMemorySymbolStream(pStream, eSymbolFormatPDB);
7509 }
7510 #endif // FEATURE_FUSION
7511
7512 #endif // DEBUGGING_SUPPORTED
7513
7514 BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, int flags, BOOL attaching)
7515 {
7516     WRAPPER_NO_CONTRACT;
7517
7518     // We don't notify the debugger about modules that don't contain any code.
7519     if (!IsVisibleToDebugger())
7520         return FALSE;
7521
7522     // Always capture metadata, even if no debugger is attached. If a debugger later attaches, it will use
7523     // this data.
7524     {
7525         Module * pModule = pDomainFile->GetModule();
7526         pModule->UpdateDynamicMetadataIfNeeded();
7527     }
7528
7529 #ifdef FEATURE_FUSION
7530     // Eagerly fetch pdbs for hosted modules.
7531     // This is only needed for debugging, so errors are not fatal in normal cases.
7532     HRESULT hrFetchPdbs = S_OK;
7533     EX_TRY
7534     {
7535         FetchPdbsFromHost();
7536     }
7537     EX_CATCH_HRESULT(hrFetchPdbs);
7538 #endif // FEATURE_FUSION
7539
7540     //
7541     // Remaining work is only needed if a debugger is attached
7542     // 
7543     if (!attaching && !pDomain->IsDebuggerAttached())
7544         return FALSE;
7545         
7546
7547     BOOL result = FALSE;
7548
7549     if (flags & ATTACH_MODULE_LOAD)
7550     {
7551         g_pDebugInterface->LoadModule(this,
7552                                       m_file->GetPath(),
7553                                       m_file->GetPath().GetCount(),
7554                                       GetAssembly(), 
7555                                       pDomain, 
7556                                       pDomainFile, 
7557                                       attaching);
7558
7559         result = TRUE;
7560     }
7561
7562     if (flags & ATTACH_CLASS_LOAD)
7563     {
7564         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
7565         while (typeDefIter.Next())
7566         {
7567             MethodTable * pMT = typeDefIter.GetElement();
7568
7569             if (pMT != NULL && pMT->IsRestored())
7570             {
7571                 result = TypeHandle(pMT).NotifyDebuggerLoad(pDomain, attaching) || result;
7572             }
7573         }
7574     }
7575
7576     return result;
7577 }
7578
7579 void Module::NotifyDebuggerUnload(AppDomain *pDomain)
7580 {
7581     LIMITED_METHOD_CONTRACT;
7582
7583     if (!pDomain->IsDebuggerAttached())
7584         return;
7585
7586     // We don't notify the debugger about modules that don't contain any code.
7587     if (!IsVisibleToDebugger())
7588         return;
7589
7590     LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
7591     while (typeDefIter.Next())
7592     {
7593         MethodTable * pMT = typeDefIter.GetElement();
7594
7595         if (pMT != NULL && pMT->IsRestored())
7596         {
7597             TypeHandle(pMT).NotifyDebuggerUnload(pDomain);
7598         }
7599     }
7600
7601     g_pDebugInterface->UnloadModule(this, pDomain);
7602 }
7603
7604 #if defined(FEATURE_MIXEDMODE) && !defined(CROSSGEN_COMPILE)
7605
7606 //======================================================================================
7607 // These are used to call back to the shim to get the information about
7608 // thunks, and to set the new targets.
7609 typedef mdToken STDMETHODCALLTYPE GetTokenForVTableEntry_t(HINSTANCE hInst, BYTE **ppVTEntry);
7610 typedef void STDMETHODCALLTYPE SetTargetForVTableEntry_t(HINSTANCE hInst, BYTE **ppVTEntry, BYTE *pTarget);
7611 typedef BYTE * STDMETHODCALLTYPE GetTargetForVTableEntry_t(HINSTANCE hInst, BYTE **ppVTEntry);
7612
7613 GetTokenForVTableEntry_t *g_pGetTokenForVTableEntry = NULL;
7614 SetTargetForVTableEntry_t *g_pSetTargetForVTableEntry = NULL;
7615 GetTargetForVTableEntry_t *g_pGetTargetForVTableEntry = NULL;
7616
7617 //======================================================================================
7618 void InitThunkCallbackFunctions(HINSTANCE hInstShim)
7619 {
7620     CONTRACTL {
7621         THROWS;
7622         GC_TRIGGERS;
7623     } CONTRACTL_END;
7624
7625     typedef enum {
7626         e_UNINITIALIZED,
7627         e_INITIALIZED_SUCCESS,
7628     } InitState_t;
7629
7630     static InitState_t s_state = e_UNINITIALIZED;
7631     if (s_state == e_UNINITIALIZED) {
7632         g_pGetTokenForVTableEntry = (GetTokenForVTableEntry_t *)GetProcAddress(hInstShim, "GetTokenForVTableEntry");
7633         if (g_pGetTokenForVTableEntry == NULL) {
7634             COMPlusThrow(kMissingMethodException, IDS_EE_MSCOREE_MISSING_ENTRYPOINT, W("GetTokenForVTableEntry"));
7635         }
7636         g_pSetTargetForVTableEntry = (SetTargetForVTableEntry_t *)GetProcAddress(hInstShim, "SetTargetForVTableEntry");
7637         if (g_pSetTargetForVTableEntry == NULL) {
7638             COMPlusThrow(kMissingMethodException, IDS_EE_MSCOREE_MISSING_ENTRYPOINT, W("SetTargetForVTableEntry"));
7639         }
7640         g_pGetTargetForVTableEntry = (GetTargetForVTableEntry_t *)GetProcAddress(hInstShim, "GetTargetForVTableEntry");
7641         if (g_pGetTargetForVTableEntry == NULL) {
7642             COMPlusThrow(kMissingMethodException, IDS_EE_MSCOREE_MISSING_ENTRYPOINT, W("GetTargetForVTableEntry"));
7643         }
7644         s_state = e_INITIALIZED_SUCCESS;
7645     }
7646     CONSISTENCY_CHECK(s_state != e_UNINITIALIZED);
7647 }
7648
7649 //======================================================================================
7650 void InitShimHINSTANCE()
7651 {
7652     CONTRACTL {
7653         THROWS;
7654         GC_TRIGGERS;
7655     } CONTRACTL_END;
7656
7657     if (g_hInstShim == NULL) {
7658         g_hInstShim = WszLoadLibrary(MSCOREE_SHIM_W);
7659         if (g_hInstShim == NULL) {
7660             InlineSString<80> ssErrorFormat;
7661             if(!ssErrorFormat.LoadResource(CCompRC::Optional, IDS_EE_MSCOREE_MISSING))
7662             {
7663                 // Keep this in sync with the actual message
7664                 ssErrorFormat.Set(W("MSCOREE is not loaded."));
7665             }
7666             EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, ssErrorFormat.GetUnicode());
7667         }
7668     }
7669 }
7670
7671 //======================================================================================
7672 HINSTANCE GetShimHINSTANCE() // dead code?
7673 {
7674     WRAPPER_NO_CONTRACT;
7675     InitShimHINSTANCE();
7676     return g_hInstShim;
7677 }
7678
7679 //======================================================================================
7680 // Fixup vtables stored in the header to contain pointers to method desc
7681 // prestubs rather than metadata method tokens.
7682 void Module::FixupVTables()
7683 {
7684     CONTRACTL {
7685         INSTANCE_CHECK;
7686         STANDARD_VM_CHECK;
7687     } CONTRACTL_END;
7688
7689
7690     // If we've already fixed up, or this is not an IJW module, just return.
7691     // NOTE: This relies on ILOnly files not having fixups. If this changes,
7692     //       we need to change this conditional.
7693     if (IsIJWFixedUp() || m_file->IsILOnly() || IsIntrospectionOnly()) {
7694         return;
7695     }
7696
7697     // An EEException will be thrown if either MSCOREE or any of the required
7698     // entrypoints cannot be found.
7699     InitShimHINSTANCE();
7700     InitThunkCallbackFunctions(g_hInstShim);
7701
7702     HINSTANCE hInstThis = GetFile()->GetIJWBase();
7703
7704     // <REVISIT_TODO>@todo: workaround!</REVISIT_TODO>
7705     // If we are compiling in-process, we don't want to fixup the vtables - as it
7706     // will have side effects on the other copy of the module!
7707     if (SystemDomain::GetCurrentDomain()->IsPassiveDomain()) {
7708         return;
7709     }
7710
7711 #ifdef FEATURE_PREJIT
7712     // We delayed filling in this value until the LoadLibrary occurred
7713     if (HasTls() && HasNativeImage()) {
7714         CORCOMPILE_EE_INFO_TABLE *pEEInfo = GetNativeImage()->GetNativeEEInfoTable();
7715         pEEInfo->rvaStaticTlsIndex = GetTlsIndex();
7716     }
7717 #endif
7718     // Get vtable fixup data
7719     COUNT_T cFixupRecords;
7720     IMAGE_COR_VTABLEFIXUP *pFixupTable = m_file->GetVTableFixups(&cFixupRecords);
7721
7722      // No records then return
7723     if (cFixupRecords == 0) {
7724         return;
7725     }
7726
7727     // Now, we need to take a lock to serialize fixup.
7728     PEImage::IJWFixupData *pData = PEImage::GetIJWData(m_file->GetIJWBase());
7729
7730     // If it's already been fixed (in some other appdomain), record the fact and return
7731     if (pData->IsFixedUp()) {
7732         SetIsIJWFixedUp();
7733         return;
7734     }
7735
7736     //////////////////////////////////////////////////////
7737     //
7738     // This is done in three stages:
7739     //  1. We enumerate the types we'll need to load
7740     //  2. We load the types
7741     //  3. We create and install the thunks
7742     //
7743
7744     COUNT_T cVtableThunks = 0;
7745     struct MethodLoadData
7746     {
7747         mdToken     token;
7748         MethodDesc *pMD;
7749     };
7750     MethodLoadData *rgMethodsToLoad = NULL;
7751     COUNT_T cMethodsToLoad = 0;
7752
7753     //
7754     // Stage 1
7755     //
7756
7757     // Each fixup entry describes a vtable, so iterate the vtables and sum their counts
7758     {
7759         DWORD iFixup;
7760         for (iFixup = 0; iFixup < cFixupRecords; iFixup++)
7761             cVtableThunks += pFixupTable[iFixup].Count;
7762     }
7763
7764     Thread *pThread = GetThread();
7765     StackingAllocator *pAlloc = &pThread->m_MarshalAlloc;
7766     CheckPointHolder cph(pAlloc->GetCheckpoint());
7767
7768     // Allocate the working array of tokens.
7769     cMethodsToLoad = cVtableThunks;
7770
7771     rgMethodsToLoad = new (pAlloc) MethodLoadData[cMethodsToLoad];
7772     memset(rgMethodsToLoad, 0, cMethodsToLoad*sizeof(MethodLoadData));
7773
7774     // Now take the IJW module lock and get all the tokens
7775     {
7776         // Take the lock
7777         CrstHolder lockHolder(pData->GetLock());
7778
7779         // If someone has beaten us, just return
7780         if (pData->IsFixedUp())
7781         {
7782             SetIsIJWFixedUp();
7783             return;
7784         }
7785
7786         COUNT_T iCurMethod = 0;
7787
7788         if (cFixupRecords != 0)
7789         {
7790             for (COUNT_T iFixup = 0; iFixup < cFixupRecords; iFixup++)
7791             {
7792                 // Vtables can be 32 or 64 bit.
7793                 if ((pFixupTable[iFixup].Type == (COR_VTABLE_PTRSIZED)) ||
7794                     (pFixupTable[iFixup].Type == (COR_VTABLE_PTRSIZED|COR_VTABLE_FROM_UNMANAGED)) ||
7795                     (pFixupTable[iFixup].Type == (COR_VTABLE_PTRSIZED|COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN)))
7796                 {
7797                     const BYTE** pPointers = (const BYTE **) m_file->GetVTable(pFixupTable[iFixup].RVA);
7798                     for (int iMethod = 0; iMethod < pFixupTable[iFixup].Count; iMethod++)
7799                     {
7800                         if (pData->IsMethodFixedUp(iFixup,iMethod))
7801                             continue;
7802                         mdToken mdTok = (*g_pGetTokenForVTableEntry)(hInstThis, (BYTE **)(pPointers + iMethod));
7803                         CONSISTENCY_CHECK(mdTok != mdTokenNil);
7804                         rgMethodsToLoad[iCurMethod++].token = mdTok;
7805                     }
7806                 }
7807             }
7808         }
7809
7810     }
7811
7812     //
7813     // Stage 2 - Load the types
7814     //
7815
7816     {
7817         for (COUNT_T iCurMethod = 0; iCurMethod < cMethodsToLoad; iCurMethod++)
7818         {
7819             mdToken curTok = rgMethodsToLoad[iCurMethod].token;
7820             if(!GetMDImport()->IsValidToken(curTok))
7821             {
7822                 _ASSERTE(!"Invalid token in v-table fix-up table");
7823                 ThrowHR(COR_E_BADIMAGEFORMAT);
7824             }
7825
7826
7827             // Find the method desc
7828             MethodDesc *pMD;
7829
7830             {
7831                 CONTRACT_VIOLATION(LoadsTypeViolation);
7832                 pMD = FindMethodThrowing(curTok);
7833             }
7834
7835             CONSISTENCY_CHECK(CheckPointer(pMD));
7836
7837             rgMethodsToLoad[iCurMethod].pMD = pMD;
7838         }
7839     }
7840
7841     //
7842     // Stage 3 - Create the thunk data
7843     //
7844     {
7845         // Take the lock
7846         CrstHolder lockHolder(pData->GetLock());
7847
7848         // If someone has beaten us, just return
7849         if (pData->IsFixedUp())
7850         {
7851             SetIsIJWFixedUp();
7852             return;
7853         }
7854
7855         // This is the app domain which all of our U->M thunks for this module will have
7856         // affinity with.  Note that if the module is shared between multiple domains, all thunks will marshal back
7857         // to the original domain, so some of the thunks may cause a surprising domain switch to occur.
7858         // (And furthermore note that if the original domain is unloaded, all the thunks will simply throw an
7859         // exception.)
7860         //
7861         // (The essential problem is that these thunks are shared via the global process address space
7862         // rather than per domain, thus there is no context to figure out our domain from.  We could
7863         // use the current thread's domain, but that is effectively undefined in unmanaged space.)
7864         //
7865         // The bottom line is that the IJW model just doesn't fit with multiple app domain design very well, so
7866         // better to have well defined limitations than flaky behavior.
7867         //
7868         //  
7869
7870         AppDomain *pAppDomain = GetAppDomain();
7871
7872         // Used to index into rgMethodsToLoad
7873         COUNT_T iCurMethod = 0;
7874
7875
7876         // Each fixup entry describes a vtable (each slot contains a metadata token
7877         // at this stage).
7878         DWORD iFixup;
7879         for (iFixup = 0; iFixup < cFixupRecords; iFixup++)
7880             cVtableThunks += pFixupTable[iFixup].Count;
7881
7882         DWORD dwIndex=0;
7883         DWORD dwThunkIndex = 0;
7884
7885         // Now to fill in the thunk table.
7886         for (iFixup = 0; iFixup < cFixupRecords; iFixup++)
7887         {
7888             const BYTE** pPointers = (const BYTE **)
7889                 m_file->GetVTable(pFixupTable[iFixup].RVA);
7890
7891             // Vtables can be 32 or 64 bit.
7892             if (pFixupTable[iFixup].Type == COR_VTABLE_PTRSIZED)
7893             {
7894                 for (int iMethod = 0; iMethod < pFixupTable[iFixup].Count; iMethod++)
7895                 {
7896                     if (pData->IsMethodFixedUp(iFixup,iMethod))
7897                         continue;
7898
7899                     mdToken mdTok = rgMethodsToLoad[iCurMethod].token;
7900                     MethodDesc *pMD = rgMethodsToLoad[iCurMethod].pMD;
7901                     iCurMethod++;
7902
7903 #ifdef _DEBUG 
7904                     if (pMD->IsNDirect())
7905                     {
7906                         LOG((LF_IJW, LL_INFO10, "[0x%lx] <-- PINV thunk for \"%s\" (target = 0x%lx)\n",
7907                              (size_t)&(pPointers[iMethod]),  pMD->m_pszDebugMethodName,
7908                              (size_t) (((NDirectMethodDesc*)pMD)->GetNDirectTarget())));
7909                     }
7910 #endif // _DEBUG
7911
7912                     CONSISTENCY_CHECK(dwThunkIndex < cVtableThunks);
7913
7914                     // Point the local vtable slot to the thunk we created
7915                     (*g_pSetTargetForVTableEntry)(hInstThis, (BYTE **)&pPointers[iMethod], (BYTE *)pMD->GetMultiCallableAddrOfCode());
7916
7917                     pData->MarkMethodFixedUp(iFixup,iMethod);
7918
7919                     dwThunkIndex++;
7920                 }
7921
7922             }
7923             else if (pFixupTable[iFixup].Type == (COR_VTABLE_PTRSIZED|COR_VTABLE_FROM_UNMANAGED))
7924             {
7925
7926                 for (int iMethod = 0; iMethod < pFixupTable[iFixup].Count; iMethod++)
7927                 {
7928                     if (pData->IsMethodFixedUp(iFixup,iMethod))
7929                         continue;
7930
7931                     mdToken mdTok = rgMethodsToLoad[iCurMethod].token;
7932                     MethodDesc *pMD = rgMethodsToLoad[iCurMethod].pMD;
7933                     iCurMethod++;
7934                     LOG((LF_IJW, LL_INFO10, "[0x%p] <-- VTable  thunk for \"%s\" (pMD = 0x%p)\n", 
7935                         (UINT_PTR)&(pPointers[iMethod]), pMD->m_pszDebugMethodName, pMD));
7936
7937                     UMEntryThunk *pUMEntryThunk = (UMEntryThunk*)(void*)(GetDllThunkHeap()->AllocAlignedMem(sizeof(UMEntryThunk), CODE_SIZE_ALIGN)); // UMEntryThunk contains code
7938                     FillMemory(pUMEntryThunk,     sizeof(*pUMEntryThunk),     0);
7939
7940                     UMThunkMarshInfo *pUMThunkMarshInfo = (UMThunkMarshInfo*)(void*)(GetThunkHeap()->AllocAlignedMem(sizeof(UMThunkMarshInfo), CODE_SIZE_ALIGN));
7941                     FillMemory(pUMThunkMarshInfo, sizeof(*pUMThunkMarshInfo), 0);
7942
7943                     pUMThunkMarshInfo->LoadTimeInit(pMD);
7944                     pUMEntryThunk->LoadTimeInit(NULL, NULL, pUMThunkMarshInfo, pMD, pAppDomain->GetId());
7945                     (*g_pSetTargetForVTableEntry)(hInstThis, (BYTE **)&pPointers[iMethod], (BYTE *)pUMEntryThunk->GetCode());
7946
7947                     pData->MarkMethodFixedUp(iFixup,iMethod);
7948                 }
7949             }
7950             else if (pFixupTable[iFixup].Type == (COR_VTABLE_PTRSIZED|COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN))
7951             {
7952
7953                 for (int iMethod = 0; iMethod < pFixupTable[iFixup].Count; iMethod++)
7954                 {
7955                     if (pData->IsMethodFixedUp(iFixup,iMethod))
7956                         continue;
7957
7958                     mdToken mdTok = rgMethodsToLoad[iCurMethod].token;
7959                     iCurMethod++;
7960
7961                     IJWNOADThunk* pThunkLocal = new(GetDllThunkHeap()->AllocAlignedMem(sizeof(IJWNOADThunk), CODE_SIZE_ALIGN)) IJWNOADThunk(GetFile()->GetIJWBase(),dwIndex++,mdTok);
7962                     (*g_pSetTargetForVTableEntry)(hInstThis, (BYTE **)&pPointers[iMethod], (BYTE *)pThunkLocal->GetCode());
7963
7964                     pData->MarkMethodFixedUp(iFixup,iMethod);
7965                 }
7966             }
7967             else if ((pFixupTable[iFixup].Type & COR_VTABLE_NOT_PTRSIZED) == COR_VTABLE_NOT_PTRSIZED)
7968             {
7969                 // fixup type doesn't match the platform
7970                 THROW_BAD_FORMAT(BFA_FIXUP_WRONG_PLATFORM, this);
7971             }
7972             else
7973             {
7974                 _ASSERTE(!"Unknown vtable fixup type");
7975             }
7976         }
7977
7978
7979         if(!GetAssembly()->IsDomainNeutral())
7980             CreateDomainThunks();
7981
7982         SetDomainIdOfIJWFixups(pAppDomain->GetId());
7983 #ifdef FEATURE_PREJIT
7984         if (HasNativeImage()) {
7985             CORCOMPILE_EE_INFO_TABLE *pEEInfo = GetNativeImage()->GetNativeEEInfoTable();
7986
7987             if (pEEInfo->nativeEntryPointStart != 0) {
7988                 PTR_PEImageLayout pIJWLayout = m_file->GetLoadedIL();
7989                 SIZE_T base = (SIZE_T)pIJWLayout->GetBase();
7990
7991                 _ASSERTE(pIJWLayout->CheckRva((RVA)pEEInfo->nativeEntryPointStart));
7992                 _ASSERTE(pIJWLayout->CheckRva((RVA)pEEInfo->nativeEntryPointEnd));
7993
7994                 pEEInfo->nativeEntryPointStart += base;
7995                 pEEInfo->nativeEntryPointEnd += base;
7996             }
7997             else {
7998                 _ASSERTE(pEEInfo->nativeEntryPointEnd == 0);
7999             }
8000         }
8001 #endif
8002         // Indicate that this module has been fixed before releasing the lock
8003         pData->SetIsFixedUp();  // On the data
8004         SetIsIJWFixedUp();      // On the module
8005     } // End of Stage 3
8006 }
8007
8008 // Self-initializing accessor for m_pThunkHeap
8009 LoaderHeap *Module::GetDllThunkHeap()
8010 {
8011     CONTRACTL
8012     {
8013         THROWS;
8014         GC_TRIGGERS;
8015         MODE_ANY;
8016     }
8017     CONTRACTL_END;
8018     return PEImage::GetDllThunkHeap(GetFile()->GetIJWBase());
8019
8020 }
8021 LoaderHeap *Module::GetThunkHeap()
8022 {
8023     CONTRACT (LoaderHeap *)
8024     {
8025         INSTANCE_CHECK;
8026         THROWS;
8027         GC_NOTRIGGER;
8028         MODE_ANY;
8029         INJECT_FAULT(COMPlusThrowOM());
8030         POSTCONDITION(CheckPointer(RETVAL));
8031     }
8032     CONTRACT_END
8033
8034     if (!m_pThunkHeap)
8035     {
8036         size_t * pPrivatePCLBytes = NULL;
8037         size_t * pGlobalPCLBytes  = NULL;
8038
8039 #ifdef PROFILING_SUPPORTED 
8040         pPrivatePCLBytes   = &(GetPerfCounters().m_Loading.cbLoaderHeapSize);
8041 #endif
8042
8043         LoaderHeap *pNewHeap = new LoaderHeap(VIRTUAL_ALLOC_RESERVE_GRANULARITY, // DWORD dwReserveBlockSize
8044                                               0,                                 // DWORD dwCommitBlockSize
8045                                               pPrivatePCLBytes,
8046                                               ThunkHeapStubManager::g_pManager->GetRangeList(),
8047                                               TRUE);                             // BOOL fMakeExecutable
8048
8049         if (FastInterlockCompareExchangePointer(&m_pThunkHeap, pNewHeap, 0) != 0)
8050         {
8051             delete pNewHeap;
8052         }
8053     }
8054
8055     RETURN m_pThunkHeap;
8056 }
8057
8058 void Module::SetADThunkTable(UMEntryThunk* pTable)
8059 {
8060     CONTRACTL
8061     {
8062         INSTANCE_CHECK;
8063         THROWS;
8064         GC_TRIGGERS;
8065         MODE_ANY;
8066     }
8067     CONTRACTL_END;
8068
8069     GetDomainLocalModule()->SetADThunkTable(pTable);
8070 }
8071
8072 UMEntryThunk* Module::GetADThunkTable()
8073 {
8074     CONTRACT(UMEntryThunk*)
8075     {
8076         INSTANCE_CHECK;
8077         THROWS;
8078         GC_TRIGGERS;
8079         MODE_ANY;
8080         INJECT_FAULT(COMPlusThrowOM());
8081         POSTCONDITION(CheckPointer(RETVAL));
8082     }
8083     CONTRACT_END
8084
8085     DomainLocalModule* pMod=GetDomainLocalModule();
8086     _ASSERTE(pMod);
8087     UMEntryThunk * pADThunkTable = pMod->GetADThunkTable();
8088     if (pADThunkTable == NULL)
8089     {
8090         CreateDomainThunks();
8091         pADThunkTable = pMod->GetADThunkTable();
8092         _ASSERTE(pADThunkTable != NULL);
8093     }
8094
8095     RETURN (UMEntryThunk*)pADThunkTable;
8096 };
8097
8098 void Module::CreateDomainThunks()
8099 {
8100     CONTRACTL
8101     {
8102         INSTANCE_CHECK;
8103         THROWS;
8104         GC_TRIGGERS;
8105         MODE_ANY;
8106         INJECT_FAULT(COMPlusThrowOM());
8107     }
8108     CONTRACTL_END;
8109
8110     AppDomain *pAppDomain = GetAppDomain();
8111     if(!pAppDomain)
8112     {
8113         _ASSERTE(!"No appdomain");
8114         return;
8115     }
8116
8117     UINT32 cFixupRecords;
8118     IMAGE_COR_VTABLEFIXUP *pFixupTable = m_file->GetVTableFixups(&cFixupRecords);
8119
8120     DWORD iFixup;
8121     DWORD cVtableThunks=0;
8122     for (iFixup = 0; iFixup < cFixupRecords; iFixup++)
8123     {
8124         if (pFixupTable[iFixup].Type==(COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN|COR_VTABLE_PTRSIZED))
8125         {
8126             cVtableThunks += pFixupTable[iFixup].Count;
8127         }
8128     }
8129
8130     if (cVtableThunks==0)
8131     {
8132         return;
8133     }
8134
8135     AllocMemTracker amTracker;
8136     AllocMemTracker *pamTracker = &amTracker;
8137
8138     UMEntryThunk* pTable=((UMEntryThunk*)pamTracker->Track(pAppDomain->GetStubHeap()->AllocAlignedMem(sizeof(UMEntryThunk)*cVtableThunks, CODE_SIZE_ALIGN)));
8139     DWORD dwCurrIndex=0;
8140     for (iFixup = 0; iFixup < cFixupRecords; iFixup++)
8141     {
8142         if (pFixupTable[iFixup].Type == (COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN|COR_VTABLE_PTRSIZED))
8143         {
8144             const BYTE **pPointers = (const BYTE **) m_file->GetVTable(pFixupTable[iFixup].RVA);
8145             for (int iMethod = 0; iMethod < pFixupTable[iFixup].Count; iMethod++)
8146             {
8147                 PCODE pCode = (PCODE)
8148                     (*g_pGetTargetForVTableEntry)((HINSTANCE)GetFile()->GetIJWBase(), (BYTE **)&pPointers[iMethod]);
8149                 IJWNOADThunk* pThnk = IJWNOADThunk::FromCode(pCode);
8150                 mdToken tok=pThnk->GetToken(); //!!
8151                 if(!GetMDImport()->IsValidToken(tok))
8152                 {
8153                     ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN);
8154                     return;
8155                 }
8156
8157                 MethodDesc *pMD = FindMethodThrowing(tok);
8158
8159                 // @TODO: Check for out of memory
8160                 UMThunkMarshInfo *pUMThunkMarshInfo = (UMThunkMarshInfo*)pamTracker->Track(pAppDomain->GetStubHeap()->AllocAlignedMem(sizeof(UMThunkMarshInfo), CODE_SIZE_ALIGN));
8161                 _ASSERTE(pUMThunkMarshInfo != NULL);
8162
8163                 pUMThunkMarshInfo->LoadTimeInit(pMD);
8164                 pTable[dwCurrIndex].LoadTimeInit(NULL, NULL, pUMThunkMarshInfo, pMD, pAppDomain->GetId());
8165
8166                 // If we're setting up a domain that is cached, update the code pointer in the cache
8167                 if (pThnk->IsCachedAppDomainID(pAppDomain->GetId()))
8168                     pThnk->SetCachedInfo(pAppDomain->GetId(), (LPVOID)GetEEFuncEntryPoint((LPVOID)pTable[dwCurrIndex].GetCode()));
8169
8170                 dwCurrIndex++;
8171             }
8172         }
8173     }
8174
8175     pamTracker->SuppressRelease();
8176     SetADThunkTable(pTable);
8177 }
8178
8179 LPVOID Module::GetUMThunk(LPVOID pManagedIp, PCCOR_SIGNATURE pSig, ULONG cSig)
8180 {
8181     CONTRACTL
8182     {
8183         THROWS;
8184         GC_TRIGGERS;
8185         MODE_ANY;
8186         CAN_TAKE_LOCK;
8187     }
8188     CONTRACTL_END;
8189
8190     return GetDomainFile()->GetUMThunk(pManagedIp, pSig, cSig);
8191 }
8192
8193
8194 void *Module::GetMUThunk(LPVOID pUnmanagedIp, PCCOR_SIGNATURE pSig, ULONG cSig)
8195 {
8196     CONTRACT (void*)
8197     {
8198         INSTANCE_CHECK;
8199         THROWS;
8200         GC_TRIGGERS;
8201         MODE_ANY;
8202         INJECT_FAULT(COMPlusThrowOM());
8203         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
8204     }
8205     CONTRACT_END
8206
8207     if (m_pMUThunkHash == NULL)
8208     {
8209         MUThunkHash *pMUThunkHash = new MUThunkHash(this);
8210         if (FastInterlockCompareExchangePointer(&m_pMUThunkHash, pMUThunkHash, NULL) != NULL)
8211             delete pMUThunkHash;
8212     }
8213     RETURN m_pMUThunkHash->GetMUThunk(pUnmanagedIp, pSig, cSig);
8214 }
8215
8216 #endif //FEATURE_MIXEDMODE && !CROSSGEN_COMPILE
8217
8218
8219 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
8220
8221 // These helpers are used in Module::ExpandAll
8222 // to avoid EX_TRY/EX_CATCH in a loop (uses _alloca and guzzles stack)
8223
8224 static TypeHandle LoadTypeDefOrRefHelper(DataImage * image, Module * pModule, mdToken tk)
8225 {
8226     STANDARD_VM_CONTRACT;
8227
8228     TypeHandle th;
8229
8230     EX_TRY
8231     {
8232         th = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tk,
8233                                               ClassLoader::ThrowIfNotFound,
8234                                               ClassLoader::PermitUninstDefOrRef);
8235     }
8236     EX_CATCH
8237     {
8238         image->GetPreloader()->Error(tk, GET_EXCEPTION());
8239     }
8240     EX_END_CATCH(SwallowAllExceptions)
8241
8242     return th;
8243 }
8244
8245 static TypeHandle LoadTypeSpecHelper(DataImage * image, Module * pModule, mdToken tk, 
8246                                      PCCOR_SIGNATURE pSig, ULONG cSig)
8247 {
8248     STANDARD_VM_CONTRACT;
8249
8250     TypeHandle th;
8251
8252     EX_TRY
8253     {
8254         SigPointer p(pSig, cSig);
8255         SigTypeContext typeContext;
8256         th = p.GetTypeHandleThrowing(pModule, &typeContext);
8257     }
8258     EX_CATCH
8259     {
8260         image->GetPreloader()->Error(tk, GET_EXCEPTION());
8261     }
8262     EX_END_CATCH(SwallowAllExceptions)
8263
8264     return th;
8265 }
8266
8267 static TypeHandle LoadGenericInstantiationHelper(DataImage * image, Module * pModule, mdToken tk, Instantiation inst)
8268 {
8269     STANDARD_VM_CONTRACT;
8270
8271     TypeHandle th;
8272
8273     EX_TRY
8274     {
8275         th = ClassLoader::LoadGenericInstantiationThrowing(pModule, tk, inst);
8276     }
8277     EX_CATCH
8278     {
8279         image->GetPreloader()->Error(tk, GET_EXCEPTION());
8280     }
8281     EX_END_CATCH(SwallowAllExceptions)
8282
8283     return th;
8284 }
8285
8286 static void GetDescFromMemberRefHelper(DataImage * image, Module * pModule, mdToken tk)
8287 {
8288     STANDARD_VM_CONTRACT;
8289
8290     EX_TRY
8291     {
8292         MethodDesc * pMD = NULL;
8293         FieldDesc * pFD = NULL;
8294         TypeHandle th;
8295
8296         // Note: using an empty type context is now OK, because even though the token is a MemberRef
8297         // neither the token nor its parent will directly refer to type variables.
8298         // @TODO GENERICS: want to allow loads of generic methods here but need strict metadata checks on parent
8299         SigTypeContext typeContext;
8300         MemberLoader::GetDescFromMemberRef(pModule, tk, &pMD, &pFD,
8301                 &typeContext,
8302                 FALSE /* strict metadata checks */, &th);
8303     }
8304     EX_CATCH
8305     {
8306         image->GetPreloader()->Error(tk, GET_EXCEPTION());
8307     }
8308     EX_END_CATCH(SwallowAllExceptions)
8309 }
8310
8311 void Module::SetProfileData(CorProfileData * profileData)
8312 {
8313     LIMITED_METHOD_CONTRACT;
8314     m_pProfileData = profileData;
8315 }
8316
8317 CorProfileData * Module::GetProfileData()
8318 {
8319     LIMITED_METHOD_CONTRACT;
8320     return m_pProfileData;
8321 }
8322
8323 mdTypeDef Module::LookupIbcTypeToken(Module *  pExternalModule, mdToken ibcToken, SString* optionalFullNameOut)
8324 {
8325     CONTRACTL
8326     {
8327         THROWS;
8328         GC_TRIGGERS;
8329         MODE_ANY;
8330     }
8331     CONTRACTL_END
8332
8333     _ASSERTE(TypeFromToken(ibcToken) == ibcExternalType);
8334
8335     CorProfileData *  profileData  = this->GetProfileData();
8336
8337     CORBBTPROF_BLOB_TYPE_DEF_ENTRY *  blobTypeDefEntry;
8338     blobTypeDefEntry = profileData->GetBlobExternalTypeDef(ibcToken);
8339
8340     if (blobTypeDefEntry == NULL)
8341         return mdTypeDefNil;
8342
8343     IbcNameHandle  ibcName;
8344     ibcName.szName           = &blobTypeDefEntry->name[0];
8345     ibcName.tkIbcNameSpace   = blobTypeDefEntry->nameSpaceToken;
8346     ibcName.tkIbcNestedClass = blobTypeDefEntry->nestedClassToken;
8347     ibcName.szNamespace      = NULL;
8348     ibcName.tkEnclosingClass = mdTypeDefNil;
8349     
8350     if (!IsNilToken(blobTypeDefEntry->nameSpaceToken))
8351     {
8352         _ASSERTE(IsNilToken(blobTypeDefEntry->nestedClassToken));
8353
8354         idExternalNamespace nameSpaceToken = blobTypeDefEntry->nameSpaceToken;
8355         _ASSERTE(TypeFromToken(nameSpaceToken) == ibcExternalNamespace);
8356
8357         CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY *  blobNamespaceDefEntry;
8358         blobNamespaceDefEntry = profileData->GetBlobExternalNamespaceDef(nameSpaceToken);
8359
8360         if (blobNamespaceDefEntry == NULL)
8361             return mdTypeDefNil;
8362
8363         ibcName.szNamespace = &blobNamespaceDefEntry->name[0];
8364
8365         if (optionalFullNameOut != NULL)
8366         {
8367             optionalFullNameOut->Append(W("["));
8368             optionalFullNameOut->AppendUTF8(pExternalModule->GetSimpleName());
8369             optionalFullNameOut->Append(W("]"));
8370
8371             if ((ibcName.szNamespace != NULL) && ((*ibcName.szNamespace) != W('\0')))
8372             {
8373                 optionalFullNameOut->AppendUTF8(ibcName.szNamespace);
8374                 optionalFullNameOut->Append(W("."));
8375             }
8376             optionalFullNameOut->AppendUTF8(ibcName.szName);
8377         }
8378     }
8379     else if (!IsNilToken(blobTypeDefEntry->nestedClassToken))
8380     {
8381         idExternalType nestedClassToken = blobTypeDefEntry->nestedClassToken;
8382         _ASSERTE(TypeFromToken(nestedClassToken) == ibcExternalType);
8383
8384         ibcName.tkEnclosingClass = LookupIbcTypeToken(pExternalModule, nestedClassToken, optionalFullNameOut);
8385
8386         if (optionalFullNameOut != NULL)
8387         {
8388             optionalFullNameOut->Append(W("+"));
8389             optionalFullNameOut->AppendUTF8(ibcName.szName);
8390         }
8391
8392         if (IsNilToken(ibcName.tkEnclosingClass))
8393             return  mdTypeDefNil;
8394     }
8395
8396     //*****************************************
8397     // look up function for TypeDef
8398     //*****************************************
8399     // STDMETHOD(FindTypeDef)(
8400     //     LPCSTR      szNamespace,            // [IN] Namespace for the TypeDef.
8401     //     LPCSTR      szName,                 // [IN] Name of the TypeDef.
8402     //     mdToken     tkEnclosingClass,       // [IN] TypeRef/TypeDef Token for the enclosing class.
8403     //     mdTypeDef   *ptypedef) PURE;        // [IN] return typedef
8404     
8405     IMDInternalImport *pInternalImport = pExternalModule->GetMDImport();
8406
8407     mdTypeDef mdResult = mdTypeDefNil;
8408
8409     HRESULT hr = pInternalImport->FindTypeDef(ibcName.szNamespace, ibcName.szName, ibcName.tkEnclosingClass, &mdResult);
8410
8411     if(FAILED(hr)) 
8412         mdResult = mdTypeDefNil;
8413
8414     return mdResult;
8415 }
8416
8417 struct IbcCompareContext
8418 {
8419     Module *         pModule;
8420     TypeHandle       enclosingType;
8421     DWORD            cMatch;      // count of methods that had a matching method name
8422     bool             useBestSig;  // if true we should use the BestSig when we don't find an exact match
8423     PCCOR_SIGNATURE  pvBestSig;   // Current Best matching signature
8424     DWORD            cbBestSig;   // 
8425 };
8426
8427 //---------------------------------------------------------------------------------------
8428 // 
8429 // Compare two signatures from the same scope. 
8430 // 
8431 BOOL 
8432 CompareIbcMethodSigs(
8433     PCCOR_SIGNATURE pvCandidateSig, // Candidate signature
8434     DWORD           cbCandidateSig, // 
8435     PCCOR_SIGNATURE pvIbcSignature, // The Ibc signature that we want to match
8436     DWORD           cbIbcSignature, // 
8437     void *          pvContext)      // void pointer to IbcCompareContext
8438 {
8439     CONTRACTL
8440     {
8441         THROWS;
8442         GC_TRIGGERS;
8443         MODE_ANY;
8444     }
8445     CONTRACTL_END
8446     
8447     //
8448     // Same pointer return TRUE
8449     // 
8450     if (pvCandidateSig == pvIbcSignature)
8451     {
8452         _ASSERTE(cbCandidateSig == cbIbcSignature);
8453         return TRUE;
8454     }
8455        
8456     //
8457     // Check for exact match
8458     // 
8459     if (cbCandidateSig == cbIbcSignature)
8460     {
8461         if (memcmp(pvCandidateSig, pvIbcSignature, cbIbcSignature) == 0)
8462         {
8463             return TRUE;
8464         }
8465     }
8466
8467     IbcCompareContext * context = (IbcCompareContext *) pvContext;
8468
8469     //
8470     // No exact match, we will return FALSE and keep looking at other matching method names
8471     // 
8472     // However since the method name was an exact match we will remember this signature,
8473     // so that if it is the best match we can look it up again and return it's methodDef token
8474     // 
8475     if (context->cMatch == 0)
8476     {
8477         context->pvBestSig = pvCandidateSig;
8478         context->cbBestSig = cbCandidateSig;
8479         context->cMatch = 1;
8480         context->useBestSig = true;
8481     }
8482     else
8483     {
8484         context->cMatch++; 
8485
8486         SigTypeContext emptyTypeContext;
8487         SigTypeContext ibcTypeContext =  SigTypeContext(context->enclosingType);
8488         MetaSig ibcSignature (pvIbcSignature, cbIbcSignature, context->pModule, &ibcTypeContext);
8489
8490         MetaSig candidateSig (pvCandidateSig, cbCandidateSig, context->pModule, &emptyTypeContext);
8491         MetaSig bestSignature(context->pvBestSig, context->cbBestSig, context->pModule, &emptyTypeContext);
8492         //
8493         // Is candidateSig a better match than bestSignature?
8494         // 
8495         // First check the calling convention
8496         // 
8497         if (candidateSig.GetCallingConventionInfo() != bestSignature.GetCallingConventionInfo())
8498         {
8499             if (bestSignature.GetCallingConventionInfo() == ibcSignature.GetCallingConventionInfo())
8500                 goto LEAVE_BEST;
8501             if (candidateSig.GetCallingConventionInfo() == ibcSignature.GetCallingConventionInfo())
8502                 goto SELECT_CANDIDATE;
8503             //
8504             // Neither one is a match
8505             // 
8506             goto USE_NEITHER;
8507         }
8508
8509         //
8510         // Next check the number of arguments
8511         // 
8512         if (candidateSig.NumFixedArgs() != bestSignature.NumFixedArgs())
8513         {
8514             //
8515             // Does one of the two have the same number of args?
8516             //
8517             if (bestSignature.NumFixedArgs() == ibcSignature.NumFixedArgs())
8518                 goto LEAVE_BEST;
8519             if (candidateSig.NumFixedArgs() == ibcSignature.NumFixedArgs())
8520                 goto SELECT_CANDIDATE;
8521             //
8522             // Neither one is a match
8523             // 
8524             goto USE_NEITHER;
8525         }
8526         else if (candidateSig.NumFixedArgs() != ibcSignature.NumFixedArgs())
8527         {
8528             //
8529             // Neither one is a match
8530             // 
8531             goto USE_NEITHER;
8532         }
8533
8534         CorElementType  etIbc; 
8535         CorElementType  etCandidate; 
8536         CorElementType  etBest; 
8537         //
8538         // Next get the return element type
8539         // 
8540         // etIbc = ibcSignature.GetReturnProps().PeekElemTypeClosed(ibcSignature.GetSigTypeContext());
8541         IfFailThrow(ibcSignature.GetReturnProps().PeekElemType(&etIbc));
8542         IfFailThrow(candidateSig.GetReturnProps().PeekElemType(&etCandidate));
8543         IfFailThrow(bestSignature.GetReturnProps().PeekElemType(&etBest));
8544         //
8545         // Do they have different return types?
8546         //
8547         if (etCandidate != etBest)
8548         {
8549             if (etBest == etIbc)
8550                 goto LEAVE_BEST;
8551
8552             if (etCandidate == etIbc)
8553                 goto SELECT_CANDIDATE;
8554         }
8555
8556         //
8557         // Now iterate over the method argument types to see which signature
8558         // is the better match
8559         // 
8560         for (DWORD i = 0; (i < ibcSignature.NumFixedArgs()); i++) 
8561         {
8562             ibcSignature.SkipArg();
8563             IfFailThrow(ibcSignature.GetArgProps().PeekElemType(&etIbc));
8564
8565             candidateSig.SkipArg();
8566             IfFailThrow(candidateSig.GetArgProps().PeekElemType(&etCandidate));
8567
8568             bestSignature.SkipArg();
8569             IfFailThrow(bestSignature.GetArgProps().PeekElemType(&etBest));
8570
8571             //
8572             // Do they have different argument types?
8573             //
8574             if (etCandidate != etBest)
8575             {
8576                 if (etBest == etIbc)
8577                     goto LEAVE_BEST;
8578
8579                 if (etCandidate == etIbc)
8580                     goto SELECT_CANDIDATE;
8581             }
8582         } 
8583         // When we fall though to here we did not find any differences
8584         // that we could base a choice on
8585         // 
8586          context->useBestSig = true;
8587
8588 SELECT_CANDIDATE:
8589         context->pvBestSig = pvCandidateSig;
8590         context->cbBestSig = cbCandidateSig;
8591         context->useBestSig = true;
8592         return FALSE;
8593
8594 USE_NEITHER:
8595         context->useBestSig = false;
8596         return FALSE;
8597     }
8598
8599 LEAVE_BEST:
8600     return FALSE;
8601 } // CompareIbcMethodSigs
8602
8603 mdMethodDef Module::LookupIbcMethodToken(TypeHandle enclosingType, mdToken ibcToken, SString* optionalFullNameOut)
8604 {
8605     CONTRACTL
8606     {
8607         THROWS;
8608         GC_TRIGGERS;
8609         MODE_ANY;
8610     }
8611     CONTRACTL_END
8612
8613     _ASSERTE(TypeFromToken(ibcToken) == ibcExternalMethod);
8614
8615     CorProfileData *  profileData  = this->GetProfileData();
8616
8617     CORBBTPROF_BLOB_METHOD_DEF_ENTRY *  blobMethodDefEntry;
8618     blobMethodDefEntry = profileData->GetBlobExternalMethodDef(ibcToken);
8619
8620     if (blobMethodDefEntry == NULL)
8621         return mdMethodDefNil;
8622
8623     idExternalType signatureToken = blobMethodDefEntry->signatureToken;
8624     _ASSERTE(!IsNilToken(signatureToken));
8625     _ASSERTE(TypeFromToken(signatureToken) == ibcExternalSignature);
8626
8627     CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY *  blobSignatureDefEntry;
8628     blobSignatureDefEntry = profileData->GetBlobExternalSignatureDef(signatureToken);
8629
8630     if (blobSignatureDefEntry == NULL)
8631         return mdMethodDefNil;
8632
8633     IbcNameHandle    ibcName;
8634     ibcName.szName                    = &blobMethodDefEntry->name[0];
8635     ibcName.tkIbcNestedClass          = blobMethodDefEntry->nestedClassToken;
8636     ibcName.tkIbcNameSpace            = idExternalNamespaceNil;
8637     ibcName.szNamespace               = NULL;
8638     ibcName.tkEnclosingClass          = mdTypeDefNil;
8639
8640     Module *         pExternalModule  = enclosingType.GetModule();
8641     PCCOR_SIGNATURE  pvSig            = NULL;
8642     ULONG            cbSig            = 0;
8643
8644     _ASSERTE(!IsNilToken(ibcName.tkIbcNestedClass));
8645     _ASSERTE(TypeFromToken(ibcName.tkIbcNestedClass) == ibcExternalType);
8646
8647     ibcName.tkEnclosingClass = LookupIbcTypeToken(pExternalModule, ibcName.tkIbcNestedClass, optionalFullNameOut);
8648        
8649     if (IsNilToken(ibcName.tkEnclosingClass))
8650         THROW_BAD_FORMAT(BFA_MISSING_IBC_EXTERNAL_TYPE, this);
8651
8652     if (optionalFullNameOut != NULL)
8653     {
8654         optionalFullNameOut->Append(W("."));
8655         optionalFullNameOut->AppendUTF8(ibcName.szName);    // MethodName
8656         optionalFullNameOut->Append(W("()"));
8657     }
8658
8659     pvSig = blobSignatureDefEntry->sig;
8660     cbSig = blobSignatureDefEntry->cSig;
8661
8662     //*****************************************
8663     // look up functions for TypeDef
8664     //*****************************************
8665     // STDMETHOD(FindMethodDefUsingCompare)(
8666     //     mdTypeDef   classdef,               // [IN] given typedef
8667     //     LPCSTR      szName,                 // [IN] member name
8668     //     PCCOR_SIGNATURE pvSigBlob,          // [IN] point to a blob value of CLR signature
8669     //     ULONG       cbSigBlob,              // [IN] count of bytes in the signature blob
8670     //     PSIGCOMPARE pSignatureCompare,      // [IN] Routine to compare signatures
8671     //     void*       pSignatureArgs,         // [IN] Additional info to supply the compare function
8672     //     mdMethodDef *pmd) PURE;             // [OUT] matching memberdef
8673     //
8674          
8675     IMDInternalImport *  pInternalImport = pExternalModule->GetMDImport();
8676
8677     IbcCompareContext context;
8678     memset(&context, 0, sizeof(IbcCompareContext));
8679     context.pModule = this;
8680     context.enclosingType = enclosingType;
8681     context.cMatch = 0;
8682     context.useBestSig = false;
8683
8684     mdMethodDef mdResult = mdMethodDefNil;
8685     HRESULT hr = pInternalImport->FindMethodDefUsingCompare(ibcName.tkEnclosingClass, ibcName.szName, 
8686                                                             pvSig, cbSig, 
8687                                                             CompareIbcMethodSigs, (void *) &context,
8688                                                             &mdResult);
8689     if (SUCCEEDED(hr)) 
8690     {
8691         _ASSERTE(mdResult != mdMethodDefNil);
8692     }
8693     else if (context.useBestSig)
8694     {
8695         hr = pInternalImport->FindMethodDefUsingCompare(ibcName.tkEnclosingClass, ibcName.szName, 
8696                                                         context.pvBestSig, context.cbBestSig,
8697                                                         CompareIbcMethodSigs, (void *) &context,
8698                                                         &mdResult);
8699         _ASSERTE(SUCCEEDED(hr));
8700         _ASSERTE(mdResult != mdMethodDefNil);
8701     }
8702     else
8703     {
8704         mdResult = mdMethodDefNil;
8705     }
8706
8707     return mdResult;
8708 }
8709
8710 SString *  Module::IBCErrorNameString()
8711 {
8712     CONTRACT(SString *)
8713     {
8714         INSTANCE_CHECK;
8715         THROWS;
8716         GC_TRIGGERS;
8717         MODE_ANY;
8718         INJECT_FAULT(COMPlusThrowOM());
8719         POSTCONDITION(CheckPointer(RETVAL));
8720     }
8721     CONTRACT_END;
8722
8723     if (m_pIBCErrorNameString == NULL)
8724     {
8725         m_pIBCErrorNameString = new SString();
8726     }
8727
8728     RETURN m_pIBCErrorNameString;
8729 }
8730
8731 void Module::IBCTypeLoadFailed(CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry, 
8732                                SString& exceptionMessage, SString* typeNameError)
8733 {
8734     CONTRACTL
8735     {
8736         THROWS;
8737         GC_TRIGGERS;
8738         MODE_ANY;
8739         INJECT_FAULT(COMPlusThrowOM());
8740         PRECONDITION(CheckPointer(pBlobSigEntry));
8741     }
8742     CONTRACTL_END
8743
8744     //
8745     // Print an error message for the type load failure
8746     // 
8747     StackSString msg(W("Failed to load type token "));
8748     SString typeName;
8749
8750     char buff[16];
8751     sprintf_s(buff, COUNTOF(buff), "%08x", pBlobSigEntry->blob.token); 
8752     StackSString szToken(SString::Ascii, &buff[0]);
8753     msg += szToken;
8754
8755     if (!exceptionMessage.IsEmpty())
8756     {
8757         if ((typeNameError != NULL) && !typeNameError->IsEmpty())
8758         {
8759             msg += W(" for the profile data in ");
8760             msg.Append(exceptionMessage);
8761             msg += W(".");
8762
8763             msg += W("  The type was ");
8764             msg.Append(*typeNameError);
8765             msg += W(".");
8766         }
8767         else
8768         {
8769             msg += W(" from profile data. The error is ");
8770             msg.Append(exceptionMessage);
8771         }
8772     }
8773     msg += W("\n");
8774
8775     GetSvcLogger()->Log(msg, LogLevel_Info);
8776 }
8777
8778 void Module::IBCMethodLoadFailed(CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry, 
8779                                  SString& exceptionMessage, SString* methodNameError)
8780 {
8781     CONTRACTL
8782     {
8783         THROWS;
8784         GC_TRIGGERS;
8785         MODE_ANY;
8786         INJECT_FAULT(COMPlusThrowOM());
8787         PRECONDITION(CheckPointer(pBlobSigEntry));
8788     }
8789     CONTRACTL_END
8790
8791     //
8792     // Print an error message for the type load failure
8793     // 
8794     StackSString msg(W("Failed to load method token "));
8795
8796     char buff[16];
8797     sprintf_s(buff, COUNTOF(buff), "%08x", pBlobSigEntry->blob.token); 
8798     StackSString szToken(SString::Ascii, &buff[0]);
8799     msg += szToken;
8800
8801     if (!exceptionMessage.IsEmpty())
8802     {
8803         if ((methodNameError != NULL) && !methodNameError->IsEmpty())
8804         {
8805             msg += W(" for the profile data in ");
8806             msg.Append(exceptionMessage);
8807             msg += W(".");
8808
8809             msg += W("  The method was ");
8810             msg.Append(*methodNameError);
8811             msg += W(".\n");
8812         }
8813         else
8814         {
8815             msg += W(" from profile data. The error is ");
8816             msg.Append(exceptionMessage);
8817         }
8818     }
8819     msg += W("\n");
8820
8821     GetSvcLogger()->Log(msg, LogLevel_Info);
8822 }
8823
8824 TypeHandle Module::LoadIBCTypeHelper(CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry)
8825 {
8826     CONTRACT(TypeHandle)
8827     {
8828         NOTHROW;
8829         GC_TRIGGERS;
8830         MODE_ANY;
8831         INJECT_FAULT(COMPlusThrowOM());
8832         PRECONDITION(CheckPointer(pBlobSigEntry));
8833     }
8834     CONTRACT_END
8835
8836     TypeHandle         loadedType;
8837
8838     PCCOR_SIGNATURE    pSig = pBlobSigEntry->sig;
8839     ULONG              cSig = pBlobSigEntry->cSig;
8840
8841     SigPointer         p(pSig, cSig);
8842
8843     ZapSig::Context    zapSigContext(this, (void *)this, ZapSig::IbcTokens);
8844     ZapSig::Context *  pZapSigContext = &zapSigContext;
8845
8846     EX_TRY
8847     {
8848         IBCErrorNameString()->Clear();
8849
8850         // This is what ZapSig::FindTypeHandleFromSignature does...
8851         // 
8852         SigTypeContext typeContext;  // empty type context
8853
8854         loadedType = p.GetTypeHandleThrowing( this,
8855                                               &typeContext,
8856                                               ClassLoader::LoadTypes,
8857                                               CLASS_LOADED,
8858                                               FALSE,
8859                                               NULL,
8860                                               pZapSigContext);
8861 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
8862         g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_1);
8863 #endif
8864     }
8865     EX_CATCH
8866     {
8867         CONTRACT_VIOLATION(ThrowsViolation);
8868
8869         StackSString exceptionMessage;
8870         GET_EXCEPTION()->GetMessage(exceptionMessage);
8871         IBCTypeLoadFailed(pBlobSigEntry, exceptionMessage, IBCErrorNameString());
8872         loadedType = TypeHandle();
8873     }
8874     EX_END_CATCH(SwallowAllExceptions)
8875
8876     RETURN loadedType;
8877 }
8878
8879 //---------------------------------------------------------------------------------------
8880 // 
8881 MethodDesc* Module::LoadIBCMethodHelper(CORBBTPROF_BLOB_PARAM_SIG_ENTRY * pBlobSigEntry)
8882 {
8883     CONTRACT(MethodDesc*)
8884     {
8885         NOTHROW;
8886         GC_TRIGGERS;
8887         MODE_ANY;
8888         INJECT_FAULT(COMPlusThrowOM());
8889         PRECONDITION(CheckPointer(pBlobSigEntry));
8890     }
8891     CONTRACT_END
8892
8893     MethodDesc* pMethod = NULL;
8894
8895     PCCOR_SIGNATURE    pSig = pBlobSigEntry->sig;
8896     ULONG              cSig = pBlobSigEntry->cSig;
8897
8898     SigPointer p(pSig, cSig);
8899
8900     ZapSig::Context    zapSigContext(this, (void *)this, ZapSig::IbcTokens);
8901     ZapSig::Context *  pZapSigContext = &zapSigContext;
8902
8903     TypeHandle         enclosingType;
8904
8905     //
8906     //  First Decode and Load the enclosing type for this method
8907     //  
8908     EX_TRY
8909     {
8910         IBCErrorNameString()->Clear();
8911
8912         // This is what ZapSig::FindTypeHandleFromSignature does...
8913         //
8914         SigTypeContext typeContext;   // empty type context
8915
8916         enclosingType = p.GetTypeHandleThrowing( this,
8917                                   &typeContext,
8918                                   ClassLoader::LoadTypes,
8919                                   CLASS_LOADED,
8920                                   FALSE,
8921                                   NULL,
8922                                   pZapSigContext);
8923         IfFailThrow(p.SkipExactlyOne());
8924 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
8925         g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_2);
8926 #endif
8927     }
8928     EX_CATCH
8929     {
8930         CONTRACT_VIOLATION(ThrowsViolation);
8931
8932         StackSString exceptionMessage;
8933         GET_EXCEPTION()->GetMessage(exceptionMessage);
8934         IBCTypeLoadFailed(pBlobSigEntry, exceptionMessage, IBCErrorNameString());
8935         enclosingType = TypeHandle();
8936     }
8937     EX_END_CATCH(SwallowAllExceptions)
8938
8939     if (enclosingType.IsNull())
8940         return NULL;
8941
8942     //
8943     //  Now Decode and Load the method
8944     //  
8945     EX_TRY
8946     {
8947         MethodTable *pOwnerMT = enclosingType.GetMethodTable();
8948         _ASSERTE(pOwnerMT != NULL);
8949
8950         // decode flags
8951         DWORD methodFlags;
8952         IfFailThrow(p.GetData(&methodFlags));
8953         BOOL isInstantiatingStub = ((methodFlags & ENCODE_METHOD_SIG_InstantiatingStub) == ENCODE_METHOD_SIG_InstantiatingStub);
8954         BOOL isUnboxingStub = ((methodFlags & ENCODE_METHOD_SIG_UnboxingStub) == ENCODE_METHOD_SIG_UnboxingStub);
8955         BOOL fMethodNeedsInstantiation = ((methodFlags & ENCODE_METHOD_SIG_MethodInstantiation) == ENCODE_METHOD_SIG_MethodInstantiation);
8956         BOOL fMethodUsesSlotEncoding = ((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == ENCODE_METHOD_SIG_SlotInsteadOfToken);
8957
8958         if ( fMethodUsesSlotEncoding )
8959         {
8960             // get the method desc using slot number
8961             DWORD slot;
8962             IfFailThrow(p.GetData(&slot));
8963
8964             pMethod = pOwnerMT->GetMethodDescForSlot(slot);
8965         }
8966         else  // otherwise we use the normal metadata MethodDef token encoding and we handle ibc tokens.
8967         {
8968             //
8969             // decode method token
8970             //
8971             RID methodRid;
8972             IfFailThrow(p.GetData(&methodRid));
8973
8974             mdMethodDef methodToken; 
8975
8976             //
8977             //  Is our enclosingType from another module?
8978             //  
8979             if (this == enclosingType.GetModule())
8980             {
8981                 //
8982                 // The enclosing type is from our module 
8983                 // The method token is a normal MethodDef token
8984                 // 
8985                 methodToken = TokenFromRid(methodRid, mdtMethodDef);
8986             }
8987             else
8988             {
8989                 //
8990                 // The enclosing type is from an external module 
8991                 // The method token is a ibcExternalMethod token
8992                 //
8993                 idExternalType ibcToken = RidToToken(methodRid, ibcExternalMethod);
8994                 methodToken = this->LookupIbcMethodToken(enclosingType, ibcToken);
8995
8996                 if (IsNilToken(methodToken))
8997                 {
8998                     SString * fullTypeName = IBCErrorNameString();
8999                     fullTypeName->Clear();
9000                     this->LookupIbcMethodToken(enclosingType, ibcToken, fullTypeName);
9001
9002                     THROW_BAD_FORMAT(BFA_MISSING_IBC_EXTERNAL_METHOD, this);
9003                 }
9004             }
9005
9006
9007             SigTypeContext methodTypeContext( enclosingType );
9008             pMethod = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(
9009                                                   pOwnerMT->GetModule(),
9010                                                   methodToken,
9011                                                   &methodTypeContext,
9012                                                   FALSE,
9013                                                   FALSE );
9014         }
9015
9016         Instantiation inst;
9017
9018         // Instantiate the method if needed, or create a stub to a static method in a generic class.
9019         if (fMethodNeedsInstantiation && pMethod->HasMethodInstantiation())
9020         {
9021             DWORD nargs = pMethod->GetNumGenericMethodArgs();
9022             SIZE_T cbMem;
9023             
9024             if (!ClrSafeInt<SIZE_T>::multiply(nargs, sizeof(TypeHandle), cbMem/* passed by ref */))
9025                 ThrowHR(COR_E_OVERFLOW);
9026             
9027             TypeHandle * pInst = (TypeHandle*) _alloca(cbMem);
9028             SigTypeContext typeContext;   // empty type context
9029
9030             for (DWORD i = 0; i < nargs; i++)
9031             {
9032                 pInst[i] = p.GetTypeHandleThrowing( this,
9033                               &typeContext,
9034                               ClassLoader::LoadTypes,
9035                               CLASS_LOADED,
9036                               FALSE,
9037                               NULL,
9038                               pZapSigContext);
9039                 IfFailThrow(p.SkipExactlyOne());
9040             }
9041
9042             inst = Instantiation(pInst, nargs);
9043         }
9044         else
9045         {
9046             inst = pMethod->LoadMethodInstantiation();
9047         }
9048
9049         // This must be called even if nargs == 0, in order to create an instantiating
9050         // stub for static methods in generic classees if needed, also for BoxedEntryPointStubs
9051         // in non-generic structs.
9052         pMethod = MethodDesc::FindOrCreateAssociatedMethodDesc(pMethod, pOwnerMT,
9053                                                                isUnboxingStub,
9054                                                                inst,
9055                                                                !(isInstantiatingStub || isUnboxingStub));
9056
9057 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
9058         g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_3);
9059 #endif
9060
9061     }
9062     EX_CATCH
9063     {
9064         CONTRACT_VIOLATION(ThrowsViolation);
9065
9066         StackSString exceptionMessage;
9067         GET_EXCEPTION()->GetMessage(exceptionMessage);
9068         IBCMethodLoadFailed(pBlobSigEntry, exceptionMessage, IBCErrorNameString());
9069         pMethod = NULL;
9070     }
9071     EX_END_CATCH(SwallowAllExceptions)
9072
9073     RETURN pMethod;
9074 } // Module::LoadIBCMethodHelper
9075
9076 #ifdef FEATURE_COMINTEROP
9077 //---------------------------------------------------------------------------------------
9078 // 
9079 // This function is a workaround for missing IBC data in WinRT assemblies and
9080 // not-yet-implemented sharing of IL_STUB(__Canon arg) IL stubs for all interfaces.
9081 //
9082 static void ExpandWindowsRuntimeType(TypeHandle t, DataImage *image)
9083 {
9084     CONTRACTL
9085     {
9086         STANDARD_VM_CHECK;
9087         PRECONDITION(!t.IsNull());
9088     }
9089     CONTRACTL_END
9090
9091     if (t.IsTypeDesc())
9092         return;
9093
9094     // This array contains our poor man's IBC data - instantiations that are known to
9095     // be used by other assemblies.
9096     static const struct
9097     {
9098         LPCUTF8         m_szTypeName;
9099         BinderClassID   m_GenericBinderClassID;
9100     }
9101     rgForcedInstantiations[] = {
9102         { "Windows.UI.Xaml.Data.IGroupInfo", CLASS__IENUMERABLEGENERIC },
9103         { "Windows.UI.Xaml.UIElement",       CLASS__ILISTGENERIC       },
9104         { "Windows.UI.Xaml.Visibility",      CLASS__CLRIREFERENCEIMPL  },
9105         { "Windows.UI.Xaml.VerticalAlignment", CLASS__CLRIREFERENCEIMPL },
9106         { "Windows.UI.Xaml.HorizontalAlignment", CLASS__CLRIREFERENCEIMPL },
9107         // The following instantiations are used by Microsoft.PlayerFramework - http://playerframework.codeplex.com/
9108         { "Windows.UI.Xaml.Media.AudioCategory", CLASS__CLRIREFERENCEIMPL },
9109         { "Windows.UI.Xaml.Media.AudioDeviceType", CLASS__CLRIREFERENCEIMPL },
9110         { "Windows.UI.Xaml.Media.MediaElementState", CLASS__CLRIREFERENCEIMPL },
9111         { "Windows.UI.Xaml.Media.Stereo3DVideoRenderMode", CLASS__CLRIREFERENCEIMPL },
9112         { "Windows.UI.Xaml.Media.Stereo3DVideoPackingMode", CLASS__CLRIREFERENCEIMPL },
9113     };
9114
9115     DefineFullyQualifiedNameForClass();
9116     LPCUTF8 szTypeName = GetFullyQualifiedNameForClass(t.AsMethodTable());
9117
9118     for (SIZE_T i = 0; i < COUNTOF(rgForcedInstantiations); i++)
9119     {
9120         if (strcmp(szTypeName, rgForcedInstantiations[i].m_szTypeName) == 0)
9121         {
9122             EX_TRY
9123             {
9124                 TypeHandle thGenericType = TypeHandle(MscorlibBinder::GetClass(rgForcedInstantiations[i].m_GenericBinderClassID));
9125
9126                 Instantiation inst(&t, 1);
9127                 thGenericType.Instantiate(inst);
9128             }
9129             EX_CATCH
9130             {
9131                 image->GetPreloader()->Error(t.GetCl(), GET_EXCEPTION());
9132             }
9133             EX_END_CATCH(SwallowAllExceptions)
9134         }
9135     }
9136
9137     if (strcmp(szTypeName, "Windows.Foundation.Collections.IObservableVector`1") == 0)
9138     {
9139         EX_TRY
9140         {
9141             TypeHandle thArg = TypeHandle(g_pObjectClass);
9142
9143             Instantiation inst(&thArg, 1);
9144             t.Instantiate(inst);
9145         }
9146         EX_CATCH
9147         {
9148             image->GetPreloader()->Error(t.GetCl(), GET_EXCEPTION());
9149         }
9150         EX_END_CATCH(SwallowAllExceptions)
9151     }
9152 }
9153 #endif // FEATURE_COMINTEROP
9154
9155 //---------------------------------------------------------------------------------------
9156 // 
9157 void Module::ExpandAll(DataImage *image)
9158 {
9159     CONTRACTL
9160     {
9161         STANDARD_VM_CHECK;
9162         PRECONDITION(!IsResource());
9163     }
9164     CONTRACTL_END
9165     
9166     mdToken tk;
9167     DWORD assemblyFlags = GetAssembly()->GetFlags();
9168
9169     //
9170     // Explicitly load the global class.
9171     //
9172
9173     MethodTable *pGlobalMT = GetGlobalMethodTable();
9174
9175     //
9176     // Load all classes.  This also fills out the
9177     // RID maps for the typedefs, method defs,
9178     // and field defs.
9179     //
9180     
9181     IMDInternalImport *pInternalImport = GetMDImport();
9182     {
9183         HENUMInternalHolder hEnum(pInternalImport);
9184         hEnum.EnumTypeDefInit();
9185         
9186         while (pInternalImport->EnumTypeDefNext(&hEnum, &tk))
9187         {
9188 #ifdef FEATURE_COMINTEROP            
9189             // Skip the non-managed WinRT types since they're only used by Javascript and C++
9190             //
9191             // With WinRT files, we want to exclude certain types that cause us problems:
9192             // * Attribute types defined in Windows.Foundation.  The constructor's methodimpl flags
9193             //   specify it is an internal runtime function and gets set as an FCALL when we parse
9194             //   the type
9195             //
9196             if (IsAfContentType_WindowsRuntime(assemblyFlags))
9197             {
9198                 mdToken tkExtends;
9199                 pInternalImport->GetTypeDefProps(tk, NULL, &tkExtends);
9200                 
9201                 if (TypeFromToken(tkExtends) == mdtTypeRef)
9202                 {
9203                     LPCSTR szNameSpace = NULL;
9204                     LPCSTR szName = NULL;
9205                     pInternalImport->GetNameOfTypeRef(tkExtends, &szNameSpace, &szName);
9206                     
9207                     if (!strcmp(szNameSpace, "System") && !_stricmp((szName), "Attribute"))
9208                     {
9209                         continue;
9210                     }
9211                 }
9212             }
9213 #endif // FEATURE_COMINTEROP
9214
9215             TypeHandle t = LoadTypeDefOrRefHelper(image, this, tk);
9216             
9217             if (t.IsNull()) // Skip this type
9218                 continue; 
9219
9220             if (!t.HasInstantiation())
9221             {
9222                 EEClassHashEntry_t *pBucket = NULL;
9223                 HashDatum           data;
9224                 StackSString        ssFullyQualifiedName;
9225                 mdToken             mdEncloser;
9226                 EEClassHashTable   *pTable = GetAvailableClassHash();
9227
9228                 _ASSERTE(pTable != NULL);
9229
9230                 t.GetName(ssFullyQualifiedName);
9231                 
9232                 // Convert to UTF8
9233                 StackScratchBuffer scratch;
9234                 LPCUTF8 szFullyQualifiedName = ssFullyQualifiedName.GetUTF8(scratch);
9235                 
9236                 BOOL isNested = ClassLoader::IsNested(this, tk, &mdEncloser);
9237                 EEClassHashTable::LookupContext sContext;
9238                 pBucket = pTable->GetValue(szFullyQualifiedName, &data, isNested, &sContext);
9239                 
9240                 if (isNested)
9241                 {
9242                     while (pBucket != NULL)
9243                     {
9244                         _ASSERTE (TypeFromToken(tk) == mdtTypeDef);
9245                         BOOL match = GetClassLoader()->CompareNestedEntryWithTypeDef( pInternalImport,
9246                                                                                       mdEncloser,
9247                                                                                       GetAvailableClassHash(),
9248                                                                                       pBucket->GetEncloser());
9249                         if (match)
9250                             break;
9251                         
9252                         pBucket = pTable->FindNextNestedClass(szFullyQualifiedName, &data, &sContext);
9253                     }
9254                 }
9255                 
9256                 // Save the typehandle instead of the token in the hash entry so that ngen'ed images
9257                 // don't have to lookup based on token and update this entry
9258                 if ((pBucket != NULL) && !t.IsNull() && t.IsRestored())
9259                     pBucket->SetData(t.AsPtr());
9260             }
9261             
9262             DWORD nGenericClassParams = t.GetNumGenericArgs();
9263             if (nGenericClassParams != 0)
9264             {
9265                 // For generic types, load the instantiation at Object
9266                 SIZE_T cbMem;
9267                 if (!ClrSafeInt<SIZE_T>::multiply(sizeof(TypeHandle), nGenericClassParams, cbMem/* passed by ref */))
9268                 {
9269                     ThrowHR(COR_E_OVERFLOW);
9270                 }
9271                 CQuickBytes qbGenericClassArgs;
9272                 TypeHandle *genericClassArgs = reinterpret_cast<TypeHandle*>(qbGenericClassArgs.AllocThrows(cbMem));
9273                 for (DWORD i = 0; i < nGenericClassParams; i++)
9274                 {
9275                     genericClassArgs[i] = TypeHandle(g_pCanonMethodTableClass);
9276                 }
9277                 
9278                 TypeHandle thCanonInst = LoadGenericInstantiationHelper(image, this, tk, Instantiation(genericClassArgs, nGenericClassParams));
9279
9280                 // If successful, add the instantiation to the Module's map of generic types instantiated at Object
9281                 if (!thCanonInst.IsNull() && !thCanonInst.IsTypeDesc())
9282                 {
9283                     MethodTable * pCanonMT = thCanonInst.AsMethodTable();
9284                     m_GenericTypeDefToCanonMethodTableMap.AddElement(this, RidFromToken(pCanonMT->GetCl()), pCanonMT);
9285                 }
9286             }
9287
9288 #ifdef FEATURE_COMINTEROP
9289             if (IsAfContentType_WindowsRuntime(assemblyFlags))
9290             {
9291                 ExpandWindowsRuntimeType(t, image);
9292             }
9293 #endif // FEATURE_COMINTEROP
9294         }
9295     }
9296     
9297     //
9298     // Fill out TypeRef RID map
9299     //
9300     
9301     {
9302         HENUMInternalHolder hEnum(pInternalImport);
9303         hEnum.EnumAllInit(mdtTypeRef);
9304         
9305         while (pInternalImport->EnumNext(&hEnum, &tk))
9306         {
9307             mdToken tkResolutionScope = mdTokenNil;
9308             pInternalImport->GetResolutionScopeOfTypeRef(tk, &tkResolutionScope);
9309
9310 #ifdef FEATURE_COMINTEROP            
9311             // WinRT first party files are authored with TypeRefs pointing to TypeDefs in the same module.
9312             // This causes us to load types we do not want to NGen such as custom attributes. We will not
9313             // expand any module local TypeRefs for WinMDs to prevent this.
9314             if(TypeFromToken(tkResolutionScope)==mdtModule && IsAfContentType_WindowsRuntime(assemblyFlags))
9315                 continue;
9316 #endif // FEATURE_COMINTEROP            
9317             TypeHandle t = LoadTypeDefOrRefHelper(image, this, tk);
9318
9319             if (t.IsNull()) // Skip this type
9320                 continue;
9321             
9322 #ifdef FEATURE_COMINTEROP                
9323             if (!g_fNGenWinMDResilient && TypeFromToken(tkResolutionScope) == mdtAssemblyRef)
9324             {
9325                 DWORD dwAssemblyRefFlags;
9326                 IfFailThrow(pInternalImport->GetAssemblyRefProps(tkResolutionScope, NULL, NULL, NULL, NULL, NULL, NULL, &dwAssemblyRefFlags));
9327                 
9328                 if (IsAfContentType_WindowsRuntime(dwAssemblyRefFlags))
9329                 {
9330                     Assembly *pAssembly = t.GetAssembly();
9331                     PEAssembly *pPEAssembly = pAssembly->GetManifestFile();
9332                     AssemblySpec refSpec;
9333                     refSpec.InitializeSpec(tkResolutionScope, pInternalImport);
9334                     LPCSTR psznamespace;
9335                     LPCSTR pszname;
9336                     pInternalImport->GetNameOfTypeRef(tk, &psznamespace, &pszname);
9337                     refSpec.SetWindowsRuntimeType(psznamespace, pszname);
9338                     GetAppDomain()->ToCompilationDomain()->AddDependency(&refSpec,pPEAssembly);
9339                 }
9340             }
9341 #endif // FEATURE_COMINTEROP                
9342         }
9343     }
9344     
9345     //
9346     // Load all type specs
9347     //
9348     
9349     {
9350         HENUMInternalHolder hEnum(pInternalImport);
9351         hEnum.EnumAllInit(mdtTypeSpec);
9352         
9353         while (pInternalImport->EnumNext(&hEnum, &tk))
9354         {
9355             ULONG cSig;
9356             PCCOR_SIGNATURE pSig;
9357             
9358             IfFailThrow(pInternalImport->GetTypeSpecFromToken(tk, &pSig, &cSig));
9359             
9360             // Load all types specs that do not contain variables
9361             if (SigPointer(pSig, cSig).IsPolyType(NULL) == hasNoVars)
9362             {
9363                 LoadTypeSpecHelper(image, this, tk, pSig, cSig);
9364             }
9365         }
9366     }
9367     
9368     //
9369     // Load all the reported parameterized types and methods
9370     //
9371     CORBBTPROF_BLOB_ENTRY *pBlobEntry = GetProfileData()->GetBlobStream();
9372     
9373     if (pBlobEntry != NULL)
9374     {
9375         while (pBlobEntry->TypeIsValid())
9376         {
9377             if (TypeFromToken(pBlobEntry->token) == ibcTypeSpec)
9378             {
9379                 _ASSERTE(pBlobEntry->type == ParamTypeSpec);
9380                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY *) pBlobEntry;
9381
9382                 TypeHandle th = LoadIBCTypeHelper(pBlobSigEntry);
9383                 if (!th.IsNull())
9384                 {
9385                     image->GetPreloader()->TriageTypeForZap(th, TRUE);
9386                 }
9387             }
9388             else if (TypeFromToken(pBlobEntry->token) == ibcMethodSpec)
9389             {
9390                 _ASSERTE(pBlobEntry->type == ParamMethodSpec);
9391                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY *) pBlobEntry;
9392                 
9393                 MethodDesc *pMD = LoadIBCMethodHelper(pBlobSigEntry);
9394                 if (pMD != NULL)
9395                 {
9396                     image->GetPreloader()->TriageMethodForZap(pMD, TRUE);
9397                 }
9398             }
9399             pBlobEntry = pBlobEntry->GetNextEntry();
9400         }
9401         _ASSERTE(pBlobEntry->type == EndOfBlobStream);
9402     }
9403     
9404     {
9405         //
9406         // Fill out MemberRef RID map and va sig cookies for
9407         // varargs member refs.
9408         //
9409         
9410         HENUMInternalHolder hEnum(pInternalImport);
9411         hEnum.EnumAllInit(mdtMemberRef);
9412         
9413         while (pInternalImport->EnumNext(&hEnum, &tk))
9414         {
9415             mdTypeRef parent;
9416             IfFailThrow(pInternalImport->GetParentOfMemberRef(tk, &parent));
9417
9418 #ifdef FEATURE_COMINTEROP
9419             if (IsAfContentType_WindowsRuntime(assemblyFlags) && TypeFromToken(parent) == mdtTypeRef)
9420             {
9421                 mdToken tkResolutionScope = mdTokenNil;
9422                 pInternalImport->GetResolutionScopeOfTypeRef(parent, &tkResolutionScope);
9423                 // WinRT first party files are authored with TypeRefs pointing to TypeDefs in the same module.
9424                 // This causes us to load types we do not want to NGen such as custom attributes. We will not
9425                 // expand any module local TypeRefs for WinMDs to prevent this.
9426                 if(TypeFromToken(tkResolutionScope)==mdtModule)
9427                     continue;
9428                 
9429                 LPCSTR szNameSpace = NULL;
9430                 LPCSTR szName = NULL;
9431                 if (SUCCEEDED(pInternalImport->GetNameOfTypeRef(parent, &szNameSpace, &szName)))
9432                 {                    
9433                     if (WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(&szNameSpace, &szName))
9434                     {
9435                         //
9436                         // This is a MemberRef from a redirected WinRT type
9437                         // We should skip it as managed view will never see this MemberRef anyway
9438                         // Not skipping this will result MissingMethodExceptions as members in redirected
9439                         // types doesn't exactly match their redirected CLR type counter part
9440                         //
9441                         // Typically we only need to do this for interfaces as we should never see MemberRef
9442                         // from non-interfaces, but here to keep things simple I'm skipping every memberref that
9443                         // belongs to redirected WinRT type
9444                         //
9445                         continue;
9446                     }
9447                 }
9448                 
9449             }
9450 #endif // FEATURE_COMINTEROP
9451
9452             // If the MethodRef has a TypeSpec as a parent (i.e. refers to a method on an array type
9453             // or on a generic class), then it could in turn refer to type variables of
9454             // an unknown class/method. So we don't preresolve any MemberRefs which have TypeSpecs as
9455             // parents.  The RID maps are not filled out for such tokens anyway.
9456             if (TypeFromToken(parent) != mdtTypeSpec)
9457             {
9458                 GetDescFromMemberRefHelper(image, this, tk);
9459             }
9460         }
9461     }
9462     
9463     //
9464     // Fill out binder
9465     //
9466     
9467     if (m_pBinder != NULL)
9468     {
9469         m_pBinder->BindAll();
9470     }
9471
9472 } // Module::ExpandAll
9473
9474 /* static */
9475 void Module::SaveMethodTable(DataImage *    image,
9476                              MethodTable *  pMT,
9477                              DWORD          profilingFlags)
9478 {
9479     STANDARD_VM_CONTRACT;
9480
9481     if (image->IsStored(pMT))
9482         return;
9483
9484     pMT->Save(image, profilingFlags);
9485 }
9486
9487
9488 /* static */
9489 void Module::SaveTypeHandle(DataImage *  image, 
9490                             TypeHandle   t, 
9491                             DWORD        profilingFlags)
9492 {
9493     STANDARD_VM_CONTRACT;
9494
9495     t.CheckRestore();
9496     if (t.IsTypeDesc())
9497     {
9498         TypeDesc *pTD = t.AsTypeDesc();
9499         if (!image->IsStored(pTD))
9500         {
9501             pTD->Save(image);
9502         }
9503     }
9504     else
9505     {
9506         MethodTable *pMT = t.AsMethodTable();
9507         if (pMT != NULL && !image->IsStored(pMT))
9508         {
9509             SaveMethodTable(image, pMT, profilingFlags);
9510             _ASSERTE(image->IsStored(pMT));
9511         }
9512     }
9513 #ifdef _DEBUG 
9514     if (LoggingOn(LF_JIT, LL_INFO100))
9515     {
9516         Module *pPrefModule = Module::GetPreferredZapModuleForTypeHandle(t);
9517         if (image->GetModule() != pPrefModule)
9518         {
9519             StackSString typeName;
9520             t.CheckRestore();
9521             TypeString::AppendTypeDebug(typeName, t);
9522             LOG((LF_ZAP, LL_INFO100, "The type %S was saved outside its preferred module %S\n", typeName.GetUnicode(), pPrefModule->GetPath().GetUnicode()));
9523         }
9524     }
9525 #endif // _DEBUG
9526 }
9527
9528 void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData)
9529 {
9530     STANDARD_VM_CONTRACT;
9531
9532     if (!numElements)
9533         return;
9534
9535     DWORD i = 0;
9536     DWORD totalBoxedStatics = 0;
9537
9538     // sort the tables so that
9539     // - the hot ppMT entries are at the beginning of the ppMT table
9540     // - the hot cctor entries are at the beginning of the cctorInfoHot table
9541     // - the cold cctor entries are at the end, and we make cctorInfoCold point
9542     //   the first cold entry
9543     //
9544     // the invariant in this loop is:
9545     // items 0...numElementsHot-1 are hot
9546     // items numElementsHot...i-1 are cold
9547     for (i = 0; i < numElements; i++)
9548     {
9549         MethodTable *ppMTTemp = ppMT[i];
9550
9551         // Count the number of boxed statics along the way
9552         totalBoxedStatics += ppMTTemp->GetNumBoxedRegularStatics();
9553
9554         bool hot = true; // if there's no profiling data, assume the entries are all hot.
9555         if (profileData->GetTokenFlagsData(TypeProfilingData))
9556         {
9557             if ((profileData->GetTypeProfilingFlagsOfToken(ppMTTemp->GetCl()) & (1 << ReadCCtorInfo)) == 0)
9558                 hot = false;
9559         }
9560         if (hot)
9561         {
9562             // swap ppMT[i] and ppMT[numElementsHot] to maintain the loop invariant
9563             ppMT[i] = ppMT[numElementsHot];
9564             ppMT[numElementsHot] = ppMTTemp;
9565
9566             numElementsHot++;
9567         }
9568     }
9569
9570     numHotHashes = numElementsHot ? RoundUpToPower2((numElementsHot * sizeof(PTR_MethodTable)) / CACHE_LINE_SIZE) : 0;
9571     numColdHashes = (numElements - numElementsHot) ? RoundUpToPower2(((numElements - numElementsHot) * 
9572                                                                     sizeof(PTR_MethodTable)) / CACHE_LINE_SIZE) : 0;
9573
9574     LOG((LF_ZAP, LL_INFO10, "ModuleCtorInfo::numHotHashes:  0x%4x\n", numHotHashes));
9575     if (numColdHashes != 0)
9576     {
9577         LOG((LF_ZAP, LL_INFO10, "ModuleCtorInfo::numColdHashes: 0x%4x\n", numColdHashes));
9578     }
9579
9580     // The "plus one" is so we can store the offset to the end of the array at the end of
9581     // the hashoffsets arrays, enabling faster lookups.
9582     hotHashOffsets = new DWORD[numHotHashes + 1];
9583     coldHashOffsets = new DWORD[numColdHashes + 1];
9584
9585     DWORD *hashArray = new DWORD[numElements];
9586
9587     for (i = 0; i < numElementsHot; i++)
9588     {
9589         hashArray[i] = GenerateHash(ppMT[i], HOT);
9590     }
9591     for (i = numElementsHot; i < numElements; i++)
9592     {
9593         hashArray[i] = GenerateHash(ppMT[i], COLD);
9594     }
9595
9596     // Sort the two arrays by hash values to create regions with the same hash values.
9597     ClassCtorInfoEntryArraySort cctorInfoHotSort(hashArray, ppMT, numElementsHot);
9598     ClassCtorInfoEntryArraySort cctorInfoColdSort(hashArray + numElementsHot, ppMT + numElementsHot, 
9599                                                     numElements - numElementsHot);
9600     cctorInfoHotSort.Sort();
9601     cctorInfoColdSort.Sort();
9602
9603     // Generate the indices that index into the correct "hash region" in the hot part of the ppMT array, and store 
9604     // them in the hotHashOffests arrays.
9605     DWORD curHash = 0;
9606     i = 0;
9607     while (i < numElementsHot)
9608     {
9609         if (curHash < hashArray[i])
9610         {
9611             hotHashOffsets[curHash++] = i;
9612         }
9613         else if (curHash == hashArray[i])
9614         {
9615             hotHashOffsets[curHash++] = i++;
9616         }
9617         else 
9618         {
9619             i++;
9620         }
9621     }
9622     while (curHash <= numHotHashes)
9623     {
9624         hotHashOffsets[curHash++] = numElementsHot;
9625     }
9626
9627     // Generate the indices that index into the correct "hash region" in the hot part of the ppMT array, and store 
9628     // them in the coldHashOffsets arrays.
9629     curHash = 0;
9630     i = numElementsHot;
9631     while (i < numElements)
9632     {
9633         if (curHash < hashArray[i])
9634         {
9635             coldHashOffsets[curHash++] = i;
9636         }
9637         else if (curHash == hashArray[i])
9638         {
9639             coldHashOffsets[curHash++] = i++;
9640         }
9641         else i++;
9642     }
9643     while (curHash <= numColdHashes)
9644     {
9645         coldHashOffsets[curHash++] = numElements;
9646     }
9647
9648     delete[] hashArray;
9649
9650
9651     cctorInfoHot    = new ClassCtorInfoEntry[numElements];
9652
9653     // make cctorInfoCold point to the first cold element
9654     cctorInfoCold   = cctorInfoHot + numElementsHot;
9655
9656     ppHotGCStaticsMTs   = (totalBoxedStatics != 0) ? new FixupPointer<PTR_MethodTable>[totalBoxedStatics] : NULL;
9657     numHotGCStaticsMTs  = totalBoxedStatics;
9658
9659     DWORD iGCStaticMT = 0;
9660
9661     for (i = 0; i < numElements; i++)
9662     {
9663         if (numElements == numElementsHot)
9664         {
9665             numHotGCStaticsMTs  = iGCStaticMT;
9666             numColdGCStaticsMTs = (totalBoxedStatics - iGCStaticMT);
9667
9668             // make ppColdGCStaticsMTs point to the first cold element
9669             ppColdGCStaticsMTs = ppHotGCStaticsMTs + numHotGCStaticsMTs;
9670         }
9671
9672         MethodTable* pMT = ppMT[i];
9673         ClassCtorInfoEntry* pEntry = &cctorInfoHot[i];
9674
9675         WORD numBoxedStatics = pMT->GetNumBoxedRegularStatics();
9676         pEntry->numBoxedStatics = numBoxedStatics;
9677         pEntry->hasFixedAddressVTStatics = !!pMT->HasFixedAddressVTStatics();
9678
9679         FieldDesc *pField = pMT->HasGenericsStaticsInfo() ? 
9680             pMT->GetGenericsStaticFieldDescs() : (pMT->GetApproxFieldDescListRaw() + pMT->GetNumIntroducedInstanceFields());
9681         FieldDesc *pFieldEnd = pField + pMT->GetNumStaticFields();
9682
9683         pEntry->firstBoxedStaticOffset = (DWORD)-1;
9684         pEntry->firstBoxedStaticMTIndex = (DWORD)-1;
9685
9686         DWORD numFoundBoxedStatics = 0;
9687         while (pField < pFieldEnd)
9688         {
9689             _ASSERTE(pField->IsStatic());
9690
9691             if (!pField->IsSpecialStatic() && pField->IsByValue())
9692             {
9693                 if (pEntry->firstBoxedStaticOffset == (DWORD)-1)
9694                 {
9695                     pEntry->firstBoxedStaticOffset = pField->GetOffset();
9696                     pEntry->firstBoxedStaticMTIndex = iGCStaticMT;
9697                 }
9698                 _ASSERTE(pField->GetOffset() - pEntry->firstBoxedStaticOffset 
9699                     == (iGCStaticMT - pEntry->firstBoxedStaticMTIndex) * sizeof(MethodTable*));
9700
9701                 TypeHandle th = pField->GetFieldTypeHandleThrowing();
9702                 ppHotGCStaticsMTs[iGCStaticMT++].SetValue(th.GetMethodTable());
9703
9704                 numFoundBoxedStatics++;
9705             }
9706             pField++;
9707         }
9708         _ASSERTE(numBoxedStatics == numFoundBoxedStatics);
9709     }
9710     _ASSERTE(iGCStaticMT == totalBoxedStatics);
9711
9712     if (numElementsHot > 0)
9713     {
9714         image->StoreStructure(cctorInfoHot,
9715                                 sizeof(ClassCtorInfoEntry) * numElementsHot,
9716                                 DataImage::ITEM_MODULE_CCTOR_INFO_HOT);
9717
9718         image->StoreStructure(hotHashOffsets,
9719                                 sizeof(DWORD) * (numHotHashes + 1),
9720                                 DataImage::ITEM_MODULE_CCTOR_INFO_HOT);
9721     }
9722
9723     if (numElements > 0)
9724         image->StoreStructure(ppMT,
9725                                 sizeof(MethodTable *) * numElements,
9726                                 DataImage::ITEM_MODULE_CCTOR_INFO_HOT);
9727
9728     if (numElements > numElementsHot)
9729     {
9730         image->StoreStructure(cctorInfoCold,
9731                                 sizeof(ClassCtorInfoEntry) * (numElements - numElementsHot),
9732                                 DataImage::ITEM_MODULE_CCTOR_INFO_COLD);
9733
9734         image->StoreStructure(coldHashOffsets,
9735                                 sizeof(DWORD) * (numColdHashes + 1),
9736                                 DataImage::ITEM_MODULE_CCTOR_INFO_COLD);
9737     }
9738
9739     if ( numHotGCStaticsMTs )
9740     {
9741         // Save the mt templates
9742         image->StoreStructure( ppHotGCStaticsMTs, numHotGCStaticsMTs * sizeof(MethodTable*),
9743                                 DataImage::ITEM_GC_STATIC_HANDLES_HOT);
9744     }
9745     else
9746     {
9747         ppHotGCStaticsMTs = NULL;
9748     }
9749
9750     if ( numColdGCStaticsMTs )
9751     {
9752         // Save the hot mt templates
9753         image->StoreStructure( ppColdGCStaticsMTs, numColdGCStaticsMTs * sizeof(MethodTable*),
9754                                 DataImage::ITEM_GC_STATIC_HANDLES_COLD);
9755     }
9756     else
9757     {
9758         ppColdGCStaticsMTs = NULL;
9759     }
9760 }
9761
9762 #ifdef FEATURE_REMOTING
9763 static void IsCrossAppDomainOptimizableWrapper(MethodDesc * pMD,
9764                                                DWORD* pnumDwords)
9765 {
9766     STANDARD_VM_CONTRACT;
9767
9768     GCX_COOP();
9769
9770     EX_TRY
9771     {
9772         if (pMD->GetNumGenericMethodArgs() == 0 && !pMD->IsStatic())
9773             RemotableMethodInfo::IsCrossAppDomainOptimizable(pMD, pnumDwords);
9774     }
9775     EX_CATCH
9776     {
9777         // If there is an exception, it'll mean the info for this method will remain uninitialized.
9778         // Just ignore the exception. At runtime, we'll try to initialize it
9779         // An exception is possible during ngen if all dependencies are not available
9780     }
9781     EX_END_CATCH(SwallowAllExceptions)
9782 }
9783
9784 static void PrepareRemotableMethodInfo(MethodTable * pMT)
9785 {
9786     STANDARD_VM_CONTRACT;
9787
9788     if (!pMT->HasRemotableMethodInfo())
9789         return;
9790
9791     MethodTable::MethodIterator it(pMT);
9792     for (; it.IsValid(); it.Next())
9793     {
9794         DWORD numDwords = 0;
9795         IsCrossAppDomainOptimizableWrapper(it.GetMethodDesc(), &numDwords);
9796     }
9797 }
9798 #endif // FEATURE_REMOTING
9799
9800 bool Module::AreAllClassesFullyLoaded()
9801 {
9802     STANDARD_VM_CONTRACT;
9803
9804     // Adjust for unused space
9805     IMDInternalImport *pImport = GetMDImport();
9806
9807     HENUMInternalHolder hEnum(pImport);
9808     hEnum.EnumAllInit(mdtTypeDef);
9809
9810     mdTypeDef token;
9811     while (pImport->EnumNext(&hEnum, &token))
9812     {
9813         _ASSERTE(TypeFromToken(token) == mdtTypeDef);
9814
9815         // Special care has to been taken with COR_GLOBAL_PARENT_TOKEN, as the class
9816         // may not be needed, (but we have to distinguish between not needed and threw error).
9817         if (token == COR_GLOBAL_PARENT_TOKEN &&
9818             !NeedsGlobalMethodTable())
9819         {
9820             // No EEClass for this token if there was no need for a global method table
9821             continue;
9822         }
9823
9824         TypeHandle th = LookupTypeDef(token);
9825         if (th.IsNull())
9826             return false;
9827
9828         if (!th.AsMethodTable()->IsFullyLoaded())
9829             return false;
9830     }
9831
9832     return true;
9833 }
9834
9835 void Module::PrepareTypesForSave(DataImage *image)
9836 {
9837     STANDARD_VM_CONTRACT;
9838
9839     //
9840     // Prepare typedefs
9841     //
9842     {
9843         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
9844         while (typeDefIter.Next())
9845         {
9846             MethodTable * pMT = typeDefIter.GetElement();
9847
9848             if (pMT == NULL || !pMT->IsFullyLoaded())
9849                 continue;
9850
9851 #ifdef FEATURE_REMOTING
9852             PrepareRemotableMethodInfo(pMT);
9853 #endif // FEATURE_REMOTING
9854
9855 #ifdef FEATURE_CER
9856             // If this module defines any CriticalFinalizerObject derived classes,
9857             // then we'll prepare these types for Constrained Execution Regions (CER) now.
9858             // (Normally they're prepared at object instantiation time, a little too late for ngen).
9859             PrepareCriticalType(pMT);
9860 #endif // FEATURE_CER
9861         }
9862     }
9863
9864     //
9865     // Prepare typespecs
9866     //
9867     {
9868         // Create a local copy in case the new elements are added to the hashtable during population
9869         InlineSArray<TypeHandle, 20> pTypes;
9870
9871         // Make sure the iterator is destroyed before there is a chance of loading new types
9872         {
9873             EETypeHashTable::Iterator it(m_pAvailableParamTypes);
9874             EETypeHashEntry *pEntry;
9875             while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
9876             {
9877                 TypeHandle t = pEntry->GetTypeHandle();
9878
9879                 if (t.IsTypeDesc())
9880                     continue;
9881
9882                 if (!image->GetPreloader()->IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE(t.AsPtr())))
9883                     continue;
9884
9885                 pTypes.Append(t);
9886             }
9887         }
9888
9889 #ifdef FEATURE_REMOTING
9890         for(COUNT_T i = 0; i < pTypes.GetCount(); i ++)
9891         {
9892             MethodTable * pMT = pTypes[i].AsMethodTable();
9893
9894             PrepareRemotableMethodInfo(pMT);
9895
9896             // @todo: prepare critical instantiated types?
9897         }
9898 #endif // FEATURE_REMOTING
9899     }
9900
9901     image->GetPreloader()->TriageForZap(FALSE, FALSE);
9902 }
9903
9904 static const char* const MethodTableRestoreReasonDescription[TotalMethodTables + 1] =
9905 {
9906     #undef RESTORE_REASON_FUNC
9907     #define RESTORE_REASON_FUNC(s) #s,
9908
9909     METHODTABLE_RESTORE_REASON()
9910
9911     #undef RESTORE_REASON
9912
9913     "TotalMethodTablesEvaluated"
9914 };
9915
9916
9917 // MethodDescByMethodTableTraits could be a local class in Module::Save(), but g++ doesn't like
9918 // instantiating templates with private classes.
9919 class MethodDescByMethodTableTraits : public NoRemoveSHashTraits< DefaultSHashTraits<MethodDesc *> >
9920 {
9921 public:
9922     typedef MethodTable * key_t;
9923     static MethodDesc * Null() { return NULL; }
9924     static bool IsNull(MethodDesc * pMD) { return pMD == NULL; }
9925     static MethodTable * GetKey(MethodDesc * pMD) { return pMD->GetMethodTable_NoLogging(); }
9926     static count_t Hash(MethodTable * pMT) { LIMITED_METHOD_CONTRACT; return (count_t) (UINT_PTR) pMT->GetTypeDefRid_NoLogging(); }
9927     static BOOL Equals(MethodTable * pMT1, MethodTable * pMT2)
9928     {
9929         return pMT1 == pMT2;
9930     }
9931 };
9932
9933 void Module::Save(DataImage *image)
9934 {
9935     STANDARD_VM_CONTRACT;
9936
9937     // Precompute type specific auxiliary information saved into NGen image
9938     // Note that this operation can load new types.
9939     PrepareTypesForSave(image);
9940
9941     // Cache values of all persisted flags computed from custom attributes
9942     IsNoStringInterning();
9943     IsRuntimeWrapExceptions();
9944 #ifdef FEATURE_CER
9945     GetReliabilityContract();
9946 #endif
9947     IsPreV4Assembly();
9948
9949     HasDefaultDllImportSearchPathsAttribute();
9950
9951     // Precompute property information to avoid runtime metadata lookup
9952     PopulatePropertyInfoMap();
9953
9954     // Any any elements and compute values of any LookupMap flags that were not available previously
9955     FinalizeLookupMapsPreSave(image);
9956
9957     //
9958     // Save the module
9959     //
9960
9961     ZapStoredStructure * pModuleNode = image->StoreStructure(this, sizeof(Module),
9962                                     DataImage::ITEM_MODULE);
9963
9964     m_pNGenLayoutInfo = (NGenLayoutInfo *)(void *)image->GetModule()->GetLoaderAllocator()->
9965         GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(NGenLayoutInfo)));
9966     image->StoreStructure(m_pNGenLayoutInfo, sizeof(NGenLayoutInfo), DataImage::ITEM_BINDER_ITEMS);
9967
9968     //
9969     // If we are NGening, we don't need to keep a list of va
9970     // sig cookies, as we already have a complete set (of course we do
9971     // have to persist the cookies themselves, though.
9972     //
9973
9974     //
9975     // Initialize maps of child data structures.  Note that each tables's blocks are
9976     // concantentated to a single block in the process.
9977     //
9978     CorProfileData * profileData = GetProfileData();
9979
9980     // ngen the neutral resources culture
9981     if(GetNeutralResourcesLanguage(&m_pszCultureName, &m_CultureNameLength, &m_FallbackLocation, TRUE)) {
9982         image->StoreStructure((void *) m_pszCultureName,
9983                                         (ULONG)(m_CultureNameLength + 1),
9984                                         DataImage::ITEM_BINDER_ITEMS,
9985                                         1);
9986     }
9987
9988
9989     m_TypeRefToMethodTableMap.Save(image, DataImage::ITEM_TYPEREF_MAP, profileData, mdtTypeRef);
9990     image->BindPointer(&m_TypeRefToMethodTableMap, pModuleNode, offsetof(Module, m_TypeRefToMethodTableMap));
9991
9992     if(m_pMemberRefToDescHashTable)
9993         m_pMemberRefToDescHashTable->Save(image, profileData);
9994
9995     m_TypeDefToMethodTableMap.Save(image, DataImage::ITEM_TYPEDEF_MAP, profileData, mdtTypeDef);
9996     image->BindPointer(&m_TypeDefToMethodTableMap, pModuleNode, offsetof(Module, m_TypeDefToMethodTableMap));
9997
9998     m_MethodDefToDescMap.Save(image, DataImage::ITEM_METHODDEF_MAP, profileData, mdtMethodDef);
9999     image->BindPointer(&m_MethodDefToDescMap, pModuleNode, offsetof(Module, m_MethodDefToDescMap));
10000
10001     m_FieldDefToDescMap.Save(image, DataImage::ITEM_FIELDDEF_MAP, profileData, mdtFieldDef);
10002     image->BindPointer(&m_FieldDefToDescMap, pModuleNode, offsetof(Module, m_FieldDefToDescMap));
10003
10004     m_GenericParamToDescMap.Save(image, DataImage::ITEM_GENERICPARAM_MAP, profileData, mdtGenericParam);
10005     image->BindPointer(&m_GenericParamToDescMap, pModuleNode, offsetof(Module, m_GenericParamToDescMap));
10006
10007     m_GenericTypeDefToCanonMethodTableMap.Save(image, DataImage::ITEM_GENERICTYPEDEF_MAP, profileData, mdtTypeDef);
10008     image->BindPointer(&m_GenericTypeDefToCanonMethodTableMap, pModuleNode, offsetof(Module, m_GenericTypeDefToCanonMethodTableMap));
10009
10010     if (m_pAvailableClasses)
10011         m_pAvailableClasses->Save(image, profileData);
10012
10013     //
10014     // Also save the parent maps; the contents will
10015     // need to be rewritten, but we can allocate the
10016     // space in the image.
10017     //
10018
10019     // these items have no hot list and no attribution
10020     m_FileReferencesMap.Save(image, DataImage::ITEM_FILEREF_MAP, profileData, 0);
10021     image->BindPointer(&m_FileReferencesMap, pModuleNode, offsetof(Module, m_FileReferencesMap));
10022
10023     m_ManifestModuleReferencesMap.Save(image, DataImage::ITEM_ASSEMREF_MAP, profileData, 0);
10024     image->BindPointer(&m_ManifestModuleReferencesMap, pModuleNode, offsetof(Module, m_ManifestModuleReferencesMap));
10025
10026     m_MethodDefToPropertyInfoMap.Save(image, DataImage::ITEM_PROPERTYINFO_MAP, profileData, 0, TRUE /*fCopyValues*/);
10027     image->BindPointer(&m_MethodDefToPropertyInfoMap, pModuleNode, offsetof(Module, m_MethodDefToPropertyInfoMap));
10028
10029     if (m_pBinder != NULL)
10030         m_pBinder->Save(image);
10031
10032     if (profileData)
10033     {
10034         // Store types.
10035
10036         // Saving hot things first is a very good thing, because we place items
10037         // in the order they are saved and things that have hot items are also
10038         // more likely to have their other structures touched, hence these should
10039         // also be placed together, at least if we don't have any further information to go on.
10040         // Note we place particular hot items with more care in the Arrange phase.
10041         //
10042         CORBBTPROF_TOKEN_INFO * pTypeProfilingData = profileData->GetTokenFlagsData(TypeProfilingData);
10043         DWORD                   cTypeProfilingData = profileData->GetTokenFlagsCount(TypeProfilingData);
10044
10045         for (unsigned int i = 0; i < cTypeProfilingData; i++)
10046         {
10047             CORBBTPROF_TOKEN_INFO *entry = &pTypeProfilingData[i];
10048             mdToken token = entry->token;
10049             DWORD   flags = entry->flags;
10050 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
10051             g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_4);
10052 #endif
10053
10054             if ((flags & (1 << ReadMethodTable)) == 0)
10055                 continue;
10056
10057             if (TypeFromToken(token) == mdtTypeDef)
10058             {
10059                 MethodTable *pMT = LookupTypeDef(token).GetMethodTable();
10060                 if (pMT && pMT->IsFullyLoaded())
10061                 {
10062                     SaveMethodTable(image, pMT, flags);
10063                 }
10064             }
10065             else  if (TypeFromToken(token) == ibcTypeSpec)
10066             {
10067                 CORBBTPROF_BLOB_ENTRY *pBlobEntry = profileData->GetBlobStream();
10068                 if (pBlobEntry)
10069                 {
10070                     while (pBlobEntry->TypeIsValid())
10071                     {
10072                         if (TypeFromToken(pBlobEntry->token) == ibcTypeSpec)
10073                         {
10074                             _ASSERTE(pBlobEntry->type == ParamTypeSpec);
10075                             
10076                             if (pBlobEntry->token == token)
10077                             {
10078                                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY *) pBlobEntry;
10079                                 TypeHandle th = LoadIBCTypeHelper(pBlobSigEntry);
10080                                 
10081                                 if (!th.IsNull())
10082                                 {
10083                                     // When we have stale IBC data the type could have been rejected from this image.
10084                                     if (image->GetPreloader()->IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE(th.AsPtr())))
10085                                     {
10086                                         SaveTypeHandle(image, th, flags);
10087                                     }
10088                                 }
10089                             }
10090                         }
10091                         pBlobEntry = pBlobEntry->GetNextEntry();
10092                     }
10093                     _ASSERTE(pBlobEntry->type == EndOfBlobStream);
10094                 }
10095             }
10096         }
10097
10098         if (m_pAvailableParamTypes != NULL)
10099         {
10100             // If we have V1 IBC data then we save the hot
10101             //  out-of-module generic instantiations here
10102
10103             CORBBTPROF_TOKEN_INFO * tokens_begin = profileData->GetTokenFlagsData(GenericTypeProfilingData);
10104             CORBBTPROF_TOKEN_INFO * tokens_end = tokens_begin + profileData->GetTokenFlagsCount(GenericTypeProfilingData);
10105
10106             if (tokens_begin != tokens_end)
10107             {
10108                 SArray<CORBBTPROF_TOKEN_INFO> tokens(tokens_begin, tokens_end);
10109                 tokens_begin = &tokens[0];
10110                 tokens_end = tokens_begin + tokens.GetCount();
10111
10112                 util::sort(tokens_begin, tokens_end);
10113
10114                 // enumerate AvailableParamTypes map and find all hot generic instantiations
10115                 EETypeHashTable::Iterator it(m_pAvailableParamTypes);
10116                 EETypeHashEntry *pEntry;
10117                 while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
10118                 {
10119                     TypeHandle t = pEntry->GetTypeHandle();
10120 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
10121                     g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_5);
10122 #endif
10123                     
10124                     if (t.HasInstantiation())
10125                     {
10126                         SString tokenName;
10127                         t.GetName(tokenName);
10128                         unsigned cur_token = tokenName.Hash() & 0xffff;
10129
10130                         CORBBTPROF_TOKEN_INFO * found = util::lower_bound(tokens_begin, tokens_end, CORBBTPROF_TOKEN_INFO(cur_token));
10131                         if (found != tokens_end && found->token == cur_token && (found->flags & (1 << ReadMethodTable)))
10132                         {
10133                             // When we have stale IBC data the type could have been rejected from this image.
10134                             if (image->GetPreloader()->IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE(t.AsPtr())))
10135                                 SaveTypeHandle(image, t, found->flags);
10136                         }
10137                     }
10138                 }
10139             }
10140         }
10141     }
10142
10143     //
10144     // Now save any types in the TypeDefToMethodTableMap map
10145
10146     {
10147         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
10148
10149         while (typeDefIter.Next())
10150         {
10151             MethodTable * pMT = typeDefIter.GetElement();
10152
10153             if (pMT != NULL && 
10154                 !image->IsStored(pMT) && pMT->IsFullyLoaded())
10155             {
10156                 image->BeginAssociatingStoredObjectsWithMethodTable(pMT);
10157                 SaveMethodTable(image, pMT, 0);
10158                 image->EndAssociatingStoredObjectsWithMethodTable();
10159             }
10160         }
10161     }
10162
10163     //
10164     // Now save any TypeDescs in m_GenericParamToDescMap map
10165
10166     {
10167         LookupMap<PTR_TypeVarTypeDesc>::Iterator genericParamIter(&m_GenericParamToDescMap);
10168
10169         while (genericParamIter.Next())
10170         {
10171             TypeVarTypeDesc *pTD = genericParamIter.GetElement();
10172
10173             if (pTD != NULL)
10174             {
10175                 pTD->Save(image);
10176             }
10177         }
10178     }
10179
10180 #ifdef _DEBUG
10181     SealGenericTypesAndMethods();
10182 #endif
10183
10184     //
10185     // Now save any  types in the AvailableParamTypes map
10186     //
10187     if (m_pAvailableParamTypes != NULL)
10188     {
10189         EETypeHashTable::Iterator it(m_pAvailableParamTypes);
10190         EETypeHashEntry *pEntry;
10191         while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
10192         {
10193             TypeHandle t = pEntry->GetTypeHandle();
10194
10195             if (image->GetPreloader()->IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE(t.AsPtr())))
10196             {
10197                 if (t.GetCanonicalMethodTable() != NULL)
10198                 {
10199                     image->BeginAssociatingStoredObjectsWithMethodTable(t.GetCanonicalMethodTable());
10200                     SaveTypeHandle(image, t, 0);
10201                     image->EndAssociatingStoredObjectsWithMethodTable();
10202                 }
10203                 else
10204                 {
10205                     SaveTypeHandle(image, t, 0);
10206                 }
10207             }
10208         }
10209     }
10210
10211     //
10212     // Now save any methods in the InstMethodHashTable
10213     // 
10214     if (m_pInstMethodHashTable != NULL)
10215     {
10216         //
10217         // Find all MethodDescs that we are going to save, and hash them with MethodTable as the key
10218         //
10219
10220         typedef SHash<MethodDescByMethodTableTraits> MethodDescByMethodTableHash;
10221
10222         MethodDescByMethodTableHash methodDescs;
10223
10224         InstMethodHashTable::Iterator it(m_pInstMethodHashTable);
10225         InstMethodHashEntry *pEntry;
10226         while (m_pInstMethodHashTable->FindNext(&it, &pEntry))
10227         {
10228             MethodDesc *pMD = pEntry->GetMethod();
10229
10230             _ASSERTE(!pMD->IsTightlyBoundToMethodTable());
10231
10232             if (!image->IsStored(pMD) &&
10233                 image->GetPreloader()->IsMethodInTransitiveClosureOfInstantiations(CORINFO_METHOD_HANDLE(pMD)))
10234             {
10235                 methodDescs.Add(pMD);
10236             }
10237         }
10238
10239         //
10240         // Save all MethodDescs on the same MethodTable using one chunk builder
10241         //
10242
10243         for (MethodDescByMethodTableHash::Iterator i1 = methodDescs.Begin(), end1 = methodDescs.End(); i1 != end1; i1++)
10244         {
10245             MethodDesc * pMD = *(i1);
10246             if (image->IsStored(pMD))
10247                 continue;
10248
10249             MethodTable * pMT = pMD->GetMethodTable();
10250
10251             MethodDesc::SaveChunk methodDescSaveChunk(image);
10252
10253             for (MethodDescByMethodTableHash::KeyIterator i2 = methodDescs.Begin(pMT), end2 = methodDescs.End(pMT); i2 != end2; i2++)
10254             {
10255                 _ASSERTE(!image->IsStored(*i2));
10256                 methodDescSaveChunk.Append(*i2);
10257             }
10258
10259             methodDescSaveChunk.Save();
10260         }
10261     }
10262
10263     // Now save the tables themselves
10264     if (m_pAvailableParamTypes != NULL)
10265     {
10266         m_pAvailableParamTypes->Save(image, this, profileData);
10267     }
10268
10269     if (m_pInstMethodHashTable != NULL)
10270     {
10271         m_pInstMethodHashTable->Save(image, profileData);
10272     }
10273
10274     {
10275         MethodTable * pStubMT = GetILStubCache()->GetStubMethodTable();
10276         if (pStubMT != NULL)
10277         {
10278             SaveMethodTable(image, pStubMT, 0);
10279         }
10280     }
10281
10282     if (m_pStubMethodHashTable != NULL)
10283     {
10284         m_pStubMethodHashTable->Save(image, profileData);
10285     }
10286
10287 #ifdef FEATURE_COMINTEROP
10288     // the type saving operations above had the side effect of populating m_pGuidToTypeHash
10289     if (m_pGuidToTypeHash != NULL)
10290     {
10291         m_pGuidToTypeHash->Save(image, profileData);
10292     }
10293 #endif // FEATURE_COMINTEROP
10294
10295     // Compute and save the property name set
10296     PrecomputeMatchingProperties(image);
10297     image->StoreStructure(m_propertyNameSet,
10298                           m_nPropertyNameSet * sizeof(BYTE),
10299                           DataImage::ITEM_PROPERTY_NAME_SET);
10300
10301 #ifdef FEATURE_CER
10302     // Save Constrained Execution Region (CER) fixup information (used to eagerly fixup trees of methods to avoid any runtime
10303     // induced failures when invoking the tree).
10304     if (m_pCerNgenRootTable != NULL)
10305         m_pCerNgenRootTable->Save(image, profileData);
10306 #endif
10307
10308     // Sort the list of RVA statics in an ascending order wrt the RVA
10309     // and save them.
10310     image->SaveRvaStructure();
10311
10312     // Save static data
10313     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Saving module static data\n"));
10314
10315     // We have this scenario where ngen will fail to load some classes but will generate
10316     // a valid exe, or it will choose not to save some loaded classes due to some error
10317     // conditions, where statics will be committed at runtime for the classes that ngen
10318     // wasn't able to load or save. So we can't cut down the static block size blindly if we've
10319     // failed to load or save any class. We don't think this scenario deserves complicated code
10320     // paths to get the extra working set perf (you would be pulling in the jitter if
10321     // you need any of these classes), So we are basically simplifying this down, if we failed
10322     // to load or save any class we won't compress the statics block and will persist the original
10323     // estimation. 
10324
10325     // All classes were loaded and saved, cut down the block
10326     if (AreAllClassesFullyLoaded())
10327     {
10328         // Set a mark indicating we had all our classes loaded
10329         m_pRegularStaticOffsets = (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED;
10330         m_pThreadStaticOffsets = (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED;
10331     }
10332     else
10333     {
10334         // Since not all of the classes loaded we want to zero the pointers to the offset tables so they'll be
10335         // recalculated at runtime. But we can't do that here since we might try to reload some of the failed
10336         // types during the arrange phase (as the result of trying to parse profiling data). So we'll defer
10337         // zero'ing anything until the fixup phase.
10338
10339         // Not all classes were stored, revert to uncompressed maps to support run-time changes
10340         m_TypeDefToMethodTableMap.ConvertSavedMapToUncompressed(image, DataImage::ITEM_TYPEDEF_MAP);
10341         m_MethodDefToDescMap.ConvertSavedMapToUncompressed(image, DataImage::ITEM_METHODDEF_MAP);
10342     }
10343
10344     m_ModuleCtorInfo.Save(image, profileData);
10345     image->BindPointer(&m_ModuleCtorInfo, pModuleNode, offsetof(Module, m_ModuleCtorInfo));
10346
10347     if (m_pDynamicStaticsInfo)
10348     {
10349         image->StoreStructure(m_pDynamicStaticsInfo, m_maxDynamicEntries*sizeof(DynamicStaticsInfo),
10350                                           DataImage::ITEM_DYNAMIC_STATICS_INFO_TABLE);
10351     }
10352
10353     // save the module security descriptor
10354     if (m_pModuleSecurityDescriptor)
10355     {
10356         m_pModuleSecurityDescriptor->Save(image);
10357     }
10358
10359     InlineTrackingMap *inlineTrackingMap = image->GetInlineTrackingMap();
10360     if (inlineTrackingMap) 
10361     {
10362         m_persistentInlineTrackingMap = new (image->GetHeap()) PersistentInlineTrackingMap(this);
10363         m_persistentInlineTrackingMap->Save(image, inlineTrackingMap);
10364     }
10365
10366     if (m_pNgenStats && g_CorCompileVerboseLevel >= CORCOMPILE_STATS)
10367     {
10368         GetSvcLogger()->Printf ("%-35s: %s\n", "MethodTable Restore Reason", "Count");
10369         DWORD dwTotal = 0;
10370         for (int i=0; i<TotalMethodTables; i++)
10371         {
10372             GetSvcLogger()->Printf ("%-35s: %d\n", MethodTableRestoreReasonDescription[i], m_pNgenStats->MethodTableRestoreNumReasons[i]);
10373             dwTotal += m_pNgenStats->MethodTableRestoreNumReasons[i];
10374         }
10375         GetSvcLogger()->Printf ("%-35s: %d\n", "TotalMethodTablesNeedRestore", dwTotal);
10376         GetSvcLogger()->Printf ("%-35s: %d\n", MethodTableRestoreReasonDescription[TotalMethodTables], m_pNgenStats->MethodTableRestoreNumReasons[TotalMethodTables]);
10377     }
10378 }
10379
10380
10381 #ifdef _DEBUG
10382 //
10383 // We call these methods to seal the
10384 // lists: m_pAvailableClasses and m_pAvailableParamTypes 
10385 // 
10386 void Module::SealGenericTypesAndMethods()
10387 {
10388     LIMITED_METHOD_CONTRACT;
10389     // Enforce that after this point in ngen that no more types or methods will be loaded.
10390     //
10391     // We increment the seal count here and only decrement it after we have completed the ngen image
10392     //
10393     if (m_pAvailableParamTypes != NULL)
10394     {
10395         m_pAvailableParamTypes->Seal();
10396     }
10397     if (m_pInstMethodHashTable != NULL)
10398     {
10399         m_pInstMethodHashTable->Seal();
10400     }
10401 }
10402 //
10403 // We call these methods to unseal the
10404 // lists: m_pAvailableClasses and m_pAvailableParamTypes 
10405 // 
10406 void Module::UnsealGenericTypesAndMethods()
10407 {
10408     LIMITED_METHOD_CONTRACT;
10409     // Allow us to create generic types and methods again
10410     // 
10411     // We only decrement it after we have completed the ngen image
10412     //
10413     if (m_pAvailableParamTypes != NULL)
10414     {
10415         m_pAvailableParamTypes->Unseal();
10416     }
10417     if (m_pInstMethodHashTable != NULL)
10418     {
10419         m_pInstMethodHashTable->Unseal();
10420     }
10421 }
10422 #endif
10423
10424
10425 void Module::PrepopulateDictionaries(DataImage *image, BOOL nonExpansive)
10426 {
10427     STANDARD_VM_CONTRACT;
10428
10429     // Prepopulating the dictionaries for instantiated types
10430     // is in theory an iteraive process, i.e. filling in
10431     // a dictionary slot may result in a class load of a new type whose
10432     // dictionary may itself need to be prepopulated.  The type expressions
10433     // involved can get larger, so there's no a-priori reason to expect this
10434     // process to terminate.
10435     //
10436     // Given a starting set of instantiated types, several strategies are
10437     // thus possible - no prepopulation (call this PP0), or
10438     // prepopulate only the dictionaries of the types that are in the initial
10439     // set (call this PP1), or do two iterations (call this PP2) etc. etc.
10440     // Whichever strategy we choose we can always afford to do
10441     // one round of prepopulation where we populate slots
10442     // whose corresponding resulting method/types are already loaded.
10443     // Call this PPn+PP-FINAL.
10444     //
10445     // Below we implement PP1+PP-FINAL for instantiated types and PP0+PP-FINAL
10446     // for instantiations of generic methods.  We use PP1 because most collection
10447     // classes (List, Dictionary etc.) only require one pass of prepopulation in order
10448     // to fully prepopulate the dictionary.
10449
10450     // Do PP1 for instantiated types... Do one iteration where we force type loading...
10451     // Because this phase may cause new entries to appear in the hash table we
10452     // copy the array of types to the stack before we do anything else.
10453     if (!nonExpansive && CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Prepopulate1))
10454     {
10455         if (m_pAvailableParamTypes != NULL)
10456         {
10457             // Create a local copy in case the new elements are added to the hashtable during population
10458             InlineSArray<TypeHandle, 20> pTypes;
10459
10460             EETypeHashTable::Iterator it(m_pAvailableParamTypes);
10461             EETypeHashEntry *pEntry;
10462             while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
10463             {
10464                 TypeHandle th = pEntry->GetTypeHandle();
10465                 if (th.IsTypeDesc())
10466                     continue;
10467
10468                 // Don't do prepopulation for open types - they shouldn't really have dictionaries anyway.
10469                 MethodTable * pMT = th.AsMethodTable();
10470                 if (pMT->ContainsGenericVariables())
10471                     continue;
10472
10473                 // Only do PP1 on things that land in their preferred Zap module.
10474                 // Forcing the load of dictionary entries in the case where we are
10475                 // speculatively saving a copy of an instantiation outside its preferred
10476                 // zap module is too expensive for the common collection class cases.
10477                 ///
10478                 // Invalid generic instantiations will not be fully loaded.
10479                 // We want to ignore them as touching them will re-raise the TypeLoadException
10480                 if (pMT->IsFullyLoaded() && image->GetModule() == GetPreferredZapModuleForMethodTable(pMT))
10481                 {
10482                     pTypes.Append(th);
10483                 }
10484             }
10485             it.Reset();
10486
10487             for(COUNT_T i = 0; i < pTypes.GetCount(); i ++)
10488             {
10489                 TypeHandle th = pTypes[i];
10490                 _ASSERTE(image->GetModule() == GetPreferredZapModuleForTypeHandle(th) );
10491                 _ASSERTE(!th.IsTypeDesc() && !th.ContainsGenericVariables());
10492                 th.AsMethodTable()->PrepopulateDictionary(image, FALSE /* not nonExpansive, i.e. can load types */);
10493             }
10494         }
10495     }
10496
10497     // PP-FINAL for instantiated types.
10498     // This is the final stage where we hardbind any remaining entries that map
10499     // to results that have already been loaded...
10500     // Thus we set the "nonExpansive" flag on PrepopulateDictionary
10501     // below, which may in turn greatly limit the amount of prepopulating we do
10502     // (partly because it's quite difficult to determine if some potential entries
10503     // in the dictionary are already loaded)
10504
10505     if (m_pAvailableParamTypes != NULL)
10506     {
10507         INDEBUG(DWORD nTypes = m_pAvailableParamTypes->GetCount());
10508
10509         EETypeHashTable::Iterator it(m_pAvailableParamTypes);
10510         EETypeHashEntry *pEntry;
10511         while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
10512         {
10513             TypeHandle th = pEntry->GetTypeHandle();
10514             if (th.IsTypeDesc())
10515                 continue;
10516
10517             MethodTable * pMT = th.AsMethodTable();
10518             if (pMT->ContainsGenericVariables())
10519                 continue;
10520
10521             pMT->PrepopulateDictionary(image, TRUE /* nonExpansive */);
10522         }
10523
10524         // No new instantiations should be added by nonExpansive prepopulation
10525         _ASSERTE(nTypes == m_pAvailableParamTypes->GetCount());
10526     }
10527
10528     // PP-FINAL for instantiations of generic methods.
10529     if (m_pInstMethodHashTable != NULL)
10530     {
10531         INDEBUG(DWORD nMethods = m_pInstMethodHashTable->GetCount());
10532
10533         InstMethodHashTable::Iterator it(m_pInstMethodHashTable);
10534         InstMethodHashEntry *pEntry;
10535         while (m_pInstMethodHashTable->FindNext(&it, &pEntry))
10536         {
10537             MethodDesc *pMD = pEntry->GetMethod();
10538             if (!pMD->ContainsGenericVariables())
10539             {
10540                 pMD->PrepopulateDictionary(image, TRUE /* nonExpansive */);
10541             }
10542         }
10543
10544         // No new instantiations should be added by nonExpansive prepopulation
10545         _ASSERTE(nMethods == m_pInstMethodHashTable->GetCount());
10546     }
10547 }
10548
10549 void Module::PlaceType(DataImage *image, TypeHandle th, DWORD profilingFlags)
10550 {
10551     STANDARD_VM_CONTRACT;
10552
10553     if (th.IsNull())
10554         return;
10555
10556     MethodTable *pMT = th.GetMethodTable();
10557
10558     if (pMT && pMT->GetLoaderModule() == this)
10559     {
10560         EEClass *pClass = pMT->GetClass();
10561
10562         if (profilingFlags & (1 << WriteMethodTableWriteableData))
10563         {
10564             image->PlaceStructureForAddress(pMT->GetWriteableData(),CORCOMPILE_SECTION_WRITE);
10565         }
10566
10567         if (profilingFlags & (1 << ReadMethodTable))
10568         {
10569             CorCompileSection section = CORCOMPILE_SECTION_READONLY_HOT;
10570             if (pMT->IsWriteable())
10571                 section = CORCOMPILE_SECTION_HOT_WRITEABLE;
10572             image->PlaceStructureForAddress(pMT, section);
10573
10574             if (pMT->HasInterfaceMap())
10575                 image->PlaceInternedStructureForAddress(pMT->GetInterfaceMap(), CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
10576
10577             MethodTable::VtableIndirectionSlotIterator it = pMT->IterateVtableIndirectionSlots();
10578             while (it.Next())
10579             {
10580                 image->PlaceInternedStructureForAddress(it.GetIndirectionSlot(), CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
10581             }
10582
10583             image->PlaceStructureForAddress(pMT->GetWriteableData(), CORCOMPILE_SECTION_HOT);
10584         }
10585
10586         if (profilingFlags & (1 << ReadNonVirtualSlots))
10587         {
10588             if (pMT->HasNonVirtualSlotsArray())
10589                 image->PlaceStructureForAddress(pMT->GetNonVirtualSlotsArray(), CORCOMPILE_SECTION_READONLY_HOT);
10590         }
10591
10592         if (profilingFlags & (1 << ReadDispatchMap) && pMT->HasDispatchMapSlot())
10593         {
10594             image->PlaceInternedStructureForAddress(pMT->GetDispatchMap(), CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
10595         }
10596
10597         if (profilingFlags & (1 << WriteEEClass))
10598         {
10599             image->PlaceStructureForAddress(pClass, CORCOMPILE_SECTION_WRITE);
10600
10601             if (pClass->HasOptionalFields())
10602                 image->PlaceStructureForAddress(pClass->GetOptionalFields(), CORCOMPILE_SECTION_WRITE);
10603         }
10604
10605         else if (profilingFlags & (1 << ReadEEClass))
10606         {
10607             image->PlaceStructureForAddress(pClass, CORCOMPILE_SECTION_HOT);
10608
10609             if (pClass->HasOptionalFields())
10610                 image->PlaceStructureForAddress(pClass->GetOptionalFields(), CORCOMPILE_SECTION_HOT);
10611
10612             if (pClass->GetVarianceInfo() != NULL)
10613                 image->PlaceInternedStructureForAddress(pClass->GetVarianceInfo(), CORCOMPILE_SECTION_READONLY_WARM, CORCOMPILE_SECTION_READONLY_WARM);
10614
10615 #ifdef FEATURE_COMINTEROP
10616             if (pClass->GetSparseCOMInteropVTableMap() != NULL)
10617             {
10618                 image->PlaceStructureForAddress(pClass->GetSparseCOMInteropVTableMap(), CORCOMPILE_SECTION_WARM);
10619                 image->PlaceInternedStructureForAddress(pClass->GetSparseCOMInteropVTableMap()->GetMapList(), CORCOMPILE_SECTION_READONLY_WARM, CORCOMPILE_SECTION_READONLY_WARM);
10620             }
10621 #endif
10622         }
10623
10624         if (profilingFlags & (1 << ReadFieldDescs))
10625         {
10626             image->PlaceStructureForAddress(pMT->GetApproxFieldDescListRaw(), CORCOMPILE_SECTION_READONLY_HOT);
10627         }
10628
10629         if (profilingFlags != 0)
10630         {
10631             if (pMT->HasPerInstInfo())
10632             {
10633                 Dictionary ** pPerInstInfo = pMT->GetPerInstInfo();
10634
10635                 BOOL fIsEagerBound = pMT->CanEagerBindToParentDictionaries(image, NULL);
10636
10637                 if (fIsEagerBound)
10638                 {
10639                     image->PlaceInternedStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
10640                 }
10641                 else
10642                 {
10643                     image->PlaceStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_WRITE);
10644                 }
10645             }
10646
10647             Dictionary * pDictionary = pMT->GetDictionary();
10648             if (pDictionary != NULL)
10649             {
10650                 BOOL fIsWriteable;
10651
10652                 if (!pMT->IsCanonicalMethodTable())
10653                 {
10654                     // CanEagerBindToMethodTable would not work for targeted patching here. The dictionary
10655                     // layout is sensitive to compilation order that can be changed by TP compatible changes.
10656                     BOOL canSaveSlots = (image->GetModule() == pMT->GetCanonicalMethodTable()->GetLoaderModule());
10657
10658                     fIsWriteable = pDictionary->IsWriteable(image, canSaveSlots,
10659                                            pMT->GetNumGenericArgs(),
10660                                            pMT->GetModule(),
10661                                            pClass->GetDictionaryLayout());
10662                 }
10663                 else
10664                 {
10665                     fIsWriteable = FALSE;
10666                 }
10667
10668                 if (fIsWriteable)
10669                 {
10670                     image->PlaceStructureForAddress(pDictionary, CORCOMPILE_SECTION_HOT_WRITEABLE);
10671                     image->PlaceStructureForAddress(pClass->GetDictionaryLayout(), CORCOMPILE_SECTION_WARM);
10672                 }
10673                 else
10674                 {
10675                     image->PlaceInternedStructureForAddress(pDictionary, CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
10676                 }
10677             }
10678         }
10679
10680         if (profilingFlags & (1 << ReadFieldMarshalers))
10681         {
10682             if (pClass->HasLayout() && pClass->GetLayoutInfo()->GetNumCTMFields() > 0)
10683             {
10684                 image->PlaceStructureForAddress((void *)pClass->GetLayoutInfo()->GetFieldMarshalers(), CORCOMPILE_SECTION_HOT);
10685             }
10686         }
10687     }
10688     if (th.IsTypeDesc())
10689     {
10690         if (profilingFlags & (1 << WriteTypeDesc))
10691             image->PlaceStructureForAddress(th.AsTypeDesc(), CORCOMPILE_SECTION_WRITE);
10692         else if  (profilingFlags & (1 << ReadTypeDesc))
10693             image->PlaceStructureForAddress(th.AsTypeDesc(), CORCOMPILE_SECTION_HOT);
10694         else
10695             image->PlaceStructureForAddress(th.AsTypeDesc(), CORCOMPILE_SECTION_WARM);
10696     }
10697 }
10698
10699 void Module::PlaceMethod(DataImage *image, MethodDesc *pMD, DWORD profilingFlags)
10700 {
10701     STANDARD_VM_CONTRACT;
10702
10703     if (pMD == NULL)
10704         return;
10705
10706     if (pMD->GetLoaderModule() != this)
10707         return;
10708
10709     if (profilingFlags & (1 << ReadMethodCode))
10710     {
10711         if (pMD->IsNDirect())
10712         {
10713             NDirectMethodDesc *pNMD = (NDirectMethodDesc *)pMD;
10714             image->PlaceStructureForAddress((void*) pNMD->GetWriteableData(), CORCOMPILE_SECTION_WRITE);
10715             
10716 #ifdef HAS_NDIRECT_IMPORT_PRECODE
10717             // The NDirect import thunk glue is used only if no marshaling is required
10718             if (!pNMD->MarshalingRequired())
10719             {
10720                 image->PlaceStructureForAddress((void*) pNMD->GetNDirectImportThunkGlue(), CORCOMPILE_SECTION_METHOD_PRECODE_HOT);
10721             }
10722 #endif // HAS_NDIRECT_IMPORT_PRECODE
10723
10724             // Late bound NDirect methods require their LibName at startup.
10725             if (!pNMD->IsQCall())
10726             {
10727                 image->PlaceStructureForAddress((void*) pNMD->GetLibName(), CORCOMPILE_SECTION_READONLY_HOT);
10728                 image->PlaceStructureForAddress((void*) pNMD->GetEntrypointName(), CORCOMPILE_SECTION_READONLY_HOT);
10729             }
10730         }
10731
10732 #ifdef FEATURE_COMINTEROP
10733         if (pMD->IsComPlusCall())
10734         {
10735             ComPlusCallMethodDesc *pCMD = (ComPlusCallMethodDesc *)pMD;
10736
10737             // If the ComPlusCallMethodDesc was actually used for interop, its ComPlusCallInfo should be hot.
10738             image->PlaceStructureForAddress((void*) pCMD->m_pComPlusCallInfo, CORCOMPILE_SECTION_HOT);
10739        }
10740 #endif // FEATURE_COMINTEROP
10741
10742         // Stubs-as-IL have writeable signatures sometimes, so can't place them
10743         // into read-only section. We should not get here for stubs-as-il anyway,
10744         // but we will filter them out just to be sure.
10745         if (pMD->HasStoredSig() && !pMD->IsILStub())
10746         {
10747             StoredSigMethodDesc *pSMD = (StoredSigMethodDesc*) pMD;
10748
10749             if (pSMD->HasStoredMethodSig())
10750             {
10751                 image->PlaceInternedStructureForAddress((void*) pSMD->GetStoredMethodSig(), CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
10752             }
10753         }
10754     }
10755
10756     // We store the entire hot chunk in the SECTION_WRITE section
10757     if (profilingFlags & (1 << WriteMethodDesc))
10758     {
10759         image->PlaceStructureForAddress(pMD, CORCOMPILE_SECTION_WRITE);
10760     }
10761
10762 #ifdef FEATURE_CER
10763     if (profilingFlags & (1 << ReadCerMethodList))
10764     {
10765         // protect against stale IBC data
10766         // Check if the profiling data incorrectly set the ReadCerMethodList bit.
10767         // This is more likely to happen with incremental IBC.
10768         if ((m_pCerNgenRootTable != NULL) && m_pCerNgenRootTable->IsNgenRootMethod(pMD))
10769         {
10770             image->PlaceStructureForAddress(m_pCerNgenRootTable->GetList(pMD), CORCOMPILE_SECTION_HOT);
10771         }
10772     }
10773 #endif // FEATURE_CER
10774
10775     if (profilingFlags & (1 << WriteMethodPrecode))
10776     {
10777         Precode* pPrecode = pMD->GetSavedPrecodeOrNull(image);
10778         // protect against stale IBC data
10779         if (pPrecode != NULL)
10780         {
10781             CorCompileSection section = CORCOMPILE_SECTION_METHOD_PRECODE_WRITE;
10782             if (pPrecode->IsPrebound(image))
10783                 section = CORCOMPILE_SECTION_METHOD_PRECODE_HOT;
10784             // Note: This is going to place the entire PRECODE_FIXUP chunk if we have one
10785             image->PlaceStructureForAddress(pPrecode, section);
10786         }
10787     }
10788     else if (profilingFlags & (1 << ReadMethodPrecode))
10789     {
10790         Precode* pPrecode = pMD->GetSavedPrecodeOrNull(image);
10791         // protect against stale IBC data
10792         if (pPrecode != NULL)
10793         {
10794             // Note: This is going to place the entire PRECODE_FIXUP chunk if we have one
10795             image->PlaceStructureForAddress(pPrecode, CORCOMPILE_SECTION_METHOD_PRECODE_HOT);
10796         }
10797     }
10798 }
10799
10800 void Module::Arrange(DataImage *image)
10801 {
10802     STANDARD_VM_CONTRACT;
10803
10804     // We collect IBC logging profiling data and use that to guide the layout of the image.
10805     image->PlaceStructureForAddress(this, CORCOMPILE_SECTION_MODULE);
10806
10807     // The stub method table is shared by all IL stubs in the module, so place it into the hot section
10808     MethodTable * pStubMT = GetILStubCache()->GetStubMethodTable();
10809     if (pStubMT != NULL)
10810         PlaceType(image, pStubMT, ReadMethodTable);
10811
10812     CorProfileData * profileData = GetProfileData();
10813     if (profileData)
10814     {
10815         //
10816         // Place hot type structues in the order specifiled by TypeProfilingData array
10817         //
10818         CORBBTPROF_TOKEN_INFO * pTypeProfilingData = profileData->GetTokenFlagsData(TypeProfilingData);
10819         DWORD                   cTypeProfilingData = profileData->GetTokenFlagsCount(TypeProfilingData);
10820         for (unsigned int i = 0; (i < cTypeProfilingData); i++)
10821         {
10822             CORBBTPROF_TOKEN_INFO * entry = &pTypeProfilingData[i];
10823             mdToken                 token = entry->token;
10824             DWORD                   flags = entry->flags;
10825 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
10826             g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_6);
10827 #endif
10828
10829             if (TypeFromToken(token) == mdtTypeDef)
10830             {
10831                 TypeHandle th = LookupTypeDef(token);
10832                 //
10833                 // Place a hot normal type and it's data
10834                 //
10835                 PlaceType(image, th, flags);
10836             }
10837             else if (TypeFromToken(token) == ibcTypeSpec)
10838             {
10839                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = profileData->GetBlobSigEntry(token);
10840                 
10841                 if (pBlobSigEntry == NULL)
10842                 {
10843                     //
10844                     // Print an error message for the type load failure
10845                     // 
10846                     StackSString msg(W("Did not find definition for type token "));
10847
10848                     char buff[16];
10849                     sprintf_s(buff, COUNTOF(buff), "%08x", token); 
10850                     StackSString szToken(SString::Ascii, &buff[0]);
10851                     msg += szToken;
10852                     msg += W(" in profile data.\n");
10853
10854                     GetSvcLogger()->Log(msg, LogLevel_Info);
10855                 }
10856                 else // (pBlobSigEntry  != NULL)
10857                 {
10858                     _ASSERTE(pBlobSigEntry->blob.token == token);
10859                     //
10860                     // decode generic type signature
10861                     //
10862                     TypeHandle th = LoadIBCTypeHelper(pBlobSigEntry);
10863
10864                     //
10865                     // Place a hot instantiated type and it's data
10866                     //
10867                     PlaceType(image, th, flags);
10868                 }
10869             }
10870             else if (TypeFromToken(token) == mdtFieldDef)
10871             {
10872                 FieldDesc *pFD = LookupFieldDef(token);
10873                 if (pFD && pFD->IsILOnlyRVAField())
10874                 {
10875                     if (entry->flags & (1 << RVAFieldData))
10876                     {
10877                         BYTE *pRVAData = (BYTE*) pFD->GetStaticAddressHandle(NULL);
10878                         //
10879                         // Place a hot RVA static field
10880                         //
10881                         image->PlaceStructureForAddress(pRVAData, CORCOMPILE_SECTION_RVA_STATICS_HOT);
10882                     }
10883                 }
10884             }
10885         }
10886
10887         //
10888         // Place hot methods and method data in the order specifiled by MethodProfilingData array
10889         //
10890         CORBBTPROF_TOKEN_INFO * pMethodProfilingData = profileData->GetTokenFlagsData(MethodProfilingData);
10891         DWORD                   cMethodProfilingData = profileData->GetTokenFlagsCount(MethodProfilingData);
10892         for (unsigned int i = 0; (i < cMethodProfilingData); i++)
10893         {
10894             mdToken token          = pMethodProfilingData[i].token;
10895             DWORD   profilingFlags = pMethodProfilingData[i].flags;
10896 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
10897             g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_7);
10898 #endif
10899
10900             if (TypeFromToken(token) == mdtMethodDef)
10901             {
10902                 MethodDesc *  pMD = LookupMethodDef(token);
10903                 //
10904                 // Place a hot normal method and it's data
10905                 //
10906                 PlaceMethod(image, pMD, profilingFlags);
10907             }
10908             else if (TypeFromToken(token) == ibcMethodSpec)
10909             {
10910                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = profileData->GetBlobSigEntry(token);
10911                 
10912                 if (pBlobSigEntry == NULL)
10913                 {
10914                     //
10915                     // Print an error message for the type load failure
10916                     // 
10917                     StackSString msg(W("Did not find definition for method token "));
10918
10919                     char buff[16];
10920                     sprintf_s(buff, COUNTOF(buff), "%08x", token); 
10921                     StackSString szToken(SString::Ascii, &buff[0]);
10922                     msg += szToken;
10923                     msg += W(" in profile data.\n");
10924
10925                     GetSvcLogger()->Log(msg, LogLevel_Info);
10926                 }
10927                 else // (pBlobSigEntry  != NULL)
10928                 {
10929                     _ASSERTE(pBlobSigEntry->blob.token == token);
10930                     MethodDesc * pMD = LoadIBCMethodHelper(pBlobSigEntry);
10931                     
10932                     if (pMD != NULL)
10933                     {
10934                         //
10935                         // Place a hot instantiated method and it's data
10936                         //
10937                         PlaceMethod(image, pMD, profilingFlags);
10938                     }
10939                 }
10940             }
10941         }
10942     }
10943
10944     // Now place all remaining items
10945     image->PlaceRemainingStructures();
10946 }
10947
10948 void ModuleCtorInfo::Fixup(DataImage *image)
10949 {
10950     STANDARD_VM_CONTRACT;
10951
10952     if (numElementsHot > 0)
10953     {
10954         image->FixupPointerField(this, offsetof(ModuleCtorInfo, cctorInfoHot));
10955         image->FixupPointerField(this, offsetof(ModuleCtorInfo, hotHashOffsets));
10956     }
10957     else
10958     {
10959         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, cctorInfoHot));
10960         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, hotHashOffsets));
10961     }
10962
10963     _ASSERTE(numElements > numElementsHot || numElements == numElementsHot);
10964     if (numElements > numElementsHot)
10965     {
10966         image->FixupPointerField(this, offsetof(ModuleCtorInfo, cctorInfoCold));
10967         image->FixupPointerField(this, offsetof(ModuleCtorInfo, coldHashOffsets));
10968     }
10969     else
10970     {
10971         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, cctorInfoCold));
10972         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, coldHashOffsets));
10973     }
10974
10975     if (numElements > 0)
10976     {
10977         image->FixupPointerField(this, offsetof(ModuleCtorInfo, ppMT));
10978
10979         for (DWORD i=0; i<numElements; i++)
10980         {
10981             image->FixupPointerField(ppMT, i * sizeof(ppMT[0]));
10982         }
10983     }
10984     else
10985     {
10986         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, ppMT));
10987     }
10988     
10989     if (numHotGCStaticsMTs > 0)
10990     {
10991         image->FixupPointerField(this, offsetof(ModuleCtorInfo, ppHotGCStaticsMTs));
10992
10993         image->BeginRegion(CORINFO_REGION_HOT);
10994         for (DWORD i=0; i < numHotGCStaticsMTs; i++)
10995         {
10996             image->FixupMethodTablePointer(ppHotGCStaticsMTs, &ppHotGCStaticsMTs[i]);
10997         }
10998         image->EndRegion(CORINFO_REGION_HOT);
10999     }
11000     else
11001     {
11002         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, ppHotGCStaticsMTs));
11003     }
11004
11005     if (numColdGCStaticsMTs > 0)
11006     {
11007         image->FixupPointerField(this, offsetof(ModuleCtorInfo, ppColdGCStaticsMTs));
11008
11009         image->BeginRegion(CORINFO_REGION_COLD);
11010         for (DWORD i=0; i < numColdGCStaticsMTs; i++)
11011         {
11012             image->FixupMethodTablePointer(ppColdGCStaticsMTs, &ppColdGCStaticsMTs[i]);
11013         }
11014         image->EndRegion(CORINFO_REGION_COLD);
11015     }
11016     else
11017     {
11018         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, ppColdGCStaticsMTs));
11019     }
11020 }
11021
11022 #ifdef _PREFAST_
11023 #pragma warning(push)
11024 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
11025 #endif
11026 void Module::Fixup(DataImage *image)
11027 {
11028     STANDARD_VM_CONTRACT;
11029
11030     // Propagate all changes to the image copy
11031     memcpy(image->GetImagePointer(this), (void*)this, sizeof(Module));
11032
11033     //
11034     // Zero out VTable
11035     //
11036
11037     image->ZeroPointerField(this, 0);
11038
11039     image->FixupPointerField(this, offsetof(Module, m_pNGenLayoutInfo));
11040
11041     image->ZeroField(this, offsetof(Module, m_pSimpleName), sizeof(m_pSimpleName));
11042
11043     image->ZeroField(this, offsetof(Module, m_file), sizeof(m_file));
11044
11045     image->FixupPointerField(this, offsetof(Module, m_pDllMain));
11046
11047     image->ZeroField(this, offsetof(Module, m_dwTransientFlags), sizeof(m_dwTransientFlags));
11048
11049     image->ZeroField(this, offsetof(Module, m_pVASigCookieBlock), sizeof(m_pVASigCookieBlock));
11050     image->ZeroField(this, offsetof(Module, m_pAssembly), sizeof(m_pAssembly));
11051     image->ZeroField(this, offsetof(Module, m_moduleRef), sizeof(m_moduleRef));
11052
11053     image->ZeroField(this, offsetof(Module, m_Crst), sizeof(m_Crst));
11054     image->ZeroField(this, offsetof(Module, m_FixupCrst), sizeof(m_FixupCrst));
11055
11056     image->ZeroField(this, offsetof(Module, m_pProfilingBlobTable), sizeof(m_pProfilingBlobTable));
11057     image->ZeroField(this, offsetof(Module, m_pProfileData), sizeof(m_pProfileData));
11058     image->ZeroPointerField(this, offsetof(Module, m_pIBCErrorNameString));
11059
11060     image->ZeroPointerField(this, offsetof(Module, m_pNgenStats));
11061
11062     // fixup the pointer for NeutralResourcesLanguage, if we have it cached
11063     if(!!(m_dwPersistedFlags & NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED)) {
11064         image->FixupPointerField(this, offsetof(Module, m_pszCultureName));
11065     }
11066
11067     // Fixup the property name set
11068     image->FixupPointerField(this, offsetof(Module, m_propertyNameSet));
11069
11070     //
11071     // Fixup the method table
11072     //
11073
11074     image->ZeroField(this, offsetof(Module, m_pISymUnmanagedReader), sizeof(m_pISymUnmanagedReader));
11075     image->ZeroField(this, offsetof(Module, m_ISymUnmanagedReaderCrst), sizeof(m_ISymUnmanagedReaderCrst));
11076
11077     // Clear active dependencies - they will be refilled at load time
11078     image->ZeroField(this, offsetof(Module, m_activeDependencies), sizeof(m_activeDependencies));
11079     new (image->GetImagePointer(this, offsetof(Module, m_unconditionalDependencies))) SynchronizedBitMask();
11080     image->ZeroField(this, offsetof(Module, m_unconditionalDependencies) + offsetof(SynchronizedBitMask, m_bitMaskLock) + offsetof(SimpleRWLock,m_spinCount), sizeof(m_unconditionalDependencies.m_bitMaskLock.m_spinCount));
11081     image->ZeroField(this, offsetof(Module, m_dwNumberOfActivations), sizeof(m_dwNumberOfActivations));
11082
11083     image->ZeroField(this, offsetof(Module, m_LookupTableCrst), sizeof(m_LookupTableCrst));
11084
11085     m_TypeDefToMethodTableMap.Fixup(image);
11086     m_TypeRefToMethodTableMap.Fixup(image, FALSE);
11087     m_MethodDefToDescMap.Fixup(image);
11088     m_FieldDefToDescMap.Fixup(image);
11089     if(m_pMemberRefToDescHashTable != NULL)
11090     {
11091         image->FixupPointerField(this, offsetof(Module, m_pMemberRefToDescHashTable));
11092         m_pMemberRefToDescHashTable->Fixup(image);
11093     }
11094     m_GenericParamToDescMap.Fixup(image);
11095     m_GenericTypeDefToCanonMethodTableMap.Fixup(image);
11096     m_FileReferencesMap.Fixup(image, FALSE);
11097     m_ManifestModuleReferencesMap.Fixup(image, FALSE);
11098     m_MethodDefToPropertyInfoMap.Fixup(image, FALSE);
11099
11100     image->ZeroPointerField(this, offsetof(Module, m_pILStubCache));
11101
11102     if (m_pAvailableClasses != NULL) {
11103         image->FixupPointerField(this, offsetof(Module, m_pAvailableClasses));
11104         m_pAvailableClasses->Fixup(image);
11105     }
11106
11107     image->ZeroField(this, offsetof(Module, m_pAvailableClassesCaseIns), sizeof(m_pAvailableClassesCaseIns));
11108     image->ZeroField(this, offsetof(Module, m_InstMethodHashTableCrst), sizeof(m_InstMethodHashTableCrst));
11109
11110     image->BeginRegion(CORINFO_REGION_COLD);
11111
11112     if (m_pAvailableParamTypes) {
11113         image->FixupPointerField(this, offsetof(Module, m_pAvailableParamTypes));
11114         m_pAvailableParamTypes->Fixup(image);
11115     }
11116
11117     if (m_pInstMethodHashTable) {
11118         image->FixupPointerField(this, offsetof(Module, m_pInstMethodHashTable));
11119         m_pInstMethodHashTable->Fixup(image);
11120     }
11121
11122     {
11123         MethodTable * pStubMT = GetILStubCache()->GetStubMethodTable();
11124         if (pStubMT != NULL)
11125             pStubMT->Fixup(image);
11126     }
11127
11128     if (m_pStubMethodHashTable) {
11129         image->FixupPointerField(this, offsetof(Module, m_pStubMethodHashTable));
11130         m_pStubMethodHashTable->Fixup(image);
11131     }
11132
11133 #ifdef FEATURE_COMINTEROP
11134     if (m_pGuidToTypeHash) {
11135         image->FixupPointerField(this, offsetof(Module, m_pGuidToTypeHash));
11136         m_pGuidToTypeHash->Fixup(image);
11137     }
11138 #endif // FEATURE_COMINTEROP
11139
11140     image->EndRegion(CORINFO_REGION_COLD);
11141
11142 #ifdef _DEBUG
11143     //
11144     // Unseal the generic tables:
11145     //
11146     // - We need to run managed code to serialize the Security attributes of the ngen image
11147     //   and we are now using generic types in the Security/Reflection code.
11148     // - Compilation of other modules of multimodule assemblies may add more types
11149     //   to the generic tables.
11150     //
11151     UnsealGenericTypesAndMethods();
11152 #endif
11153
11154     m_ModuleCtorInfo.Fixup(image);
11155
11156     //
11157     // Fixup binder
11158     //
11159
11160     if (m_pBinder != NULL)
11161     {
11162         image->FixupPointerField(this, offsetof(Module, m_pBinder));
11163         m_pBinder->Fixup(image);
11164     }
11165
11166
11167     //
11168     // Fixup classes
11169     //
11170
11171     {
11172         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
11173
11174         image->BeginRegion(CORINFO_REGION_COLD);
11175         while (typeDefIter.Next())
11176         {
11177             MethodTable * t = typeDefIter.GetElement();
11178             if (image->IsStored(t))
11179                 t->Fixup(image);
11180         }
11181         image->EndRegion(CORINFO_REGION_COLD);
11182     }
11183
11184     {
11185         LookupMap<PTR_TypeRef>::Iterator typeRefIter(&m_TypeRefToMethodTableMap);
11186         DWORD rid = 0;
11187
11188         image->BeginRegion(CORINFO_REGION_HOT);
11189         while (typeRefIter.Next())
11190         {
11191             TADDR flags;
11192             TypeHandle th = TypeHandle::FromTAddr(dac_cast<TADDR>(typeRefIter.GetElementAndFlags(&flags)));
11193             
11194             if (!th.IsNull())
11195             {
11196                 if (th.GetLoaderModule() != this || image->IsStored(th.AsPtr()))
11197                 {
11198                     PTR_TADDR hotItemValuePtr = m_TypeRefToMethodTableMap.FindHotItemValuePtr(rid);
11199                     BOOL fSet = FALSE;
11200                    
11201                     if (image->CanEagerBindToTypeHandle(th))
11202                     {
11203                         if (image->CanHardBindToZapModule(th.GetLoaderModule()))
11204                         {
11205                             PVOID pTarget = th.IsTypeDesc() ? th.AsTypeDesc() : th.AsPtr();
11206                             SSIZE_T offset = th.IsTypeDesc() ? 2 : 0;
11207
11208                             _ASSERTE((flags & offset) == 0);
11209
11210                             image->FixupField(m_TypeRefToMethodTableMap.pTable, rid * sizeof(TADDR), 
11211                                 pTarget, flags | offset, IMAGE_REL_BASED_RelativePointer);
11212
11213                             // In case this item is also in the hot item subtable, fix it up there as well
11214                             if (hotItemValuePtr != NULL)
11215                             {
11216                                 image->FixupField(m_TypeRefToMethodTableMap.hotItemList, 
11217                                     (BYTE *)hotItemValuePtr - (BYTE *)m_TypeRefToMethodTableMap.hotItemList,
11218                                     pTarget, flags | offset, IMAGE_REL_BASED_RelativePointer);
11219                             }
11220                             fSet = TRUE;
11221                         }
11222                         else
11223                         // Create the indirection only if the entry is hot or we do have indirection cell already
11224                         if (hotItemValuePtr != NULL || image->GetExistingTypeHandleImport(th) != NULL)
11225                         {
11226                             _ASSERTE((flags & FIXUP_POINTER_INDIRECTION) == 0);
11227
11228                             ZapNode * pImport = image->GetTypeHandleImport(th);
11229                             image->FixupFieldToNode(m_TypeRefToMethodTableMap.pTable, rid * sizeof(TADDR), 
11230                                 pImport, flags | FIXUP_POINTER_INDIRECTION, IMAGE_REL_BASED_RelativePointer);
11231                             if (hotItemValuePtr != NULL)
11232                             {
11233                                 image->FixupFieldToNode(m_TypeRefToMethodTableMap.hotItemList, 
11234                                     (BYTE *)hotItemValuePtr - (BYTE *)m_TypeRefToMethodTableMap.hotItemList, 
11235                                     pImport, flags | FIXUP_POINTER_INDIRECTION, IMAGE_REL_BASED_RelativePointer);
11236                             }
11237                             fSet = TRUE;
11238                         }
11239                     }
11240
11241                     if (!fSet)
11242                     {
11243                         image->ZeroPointerField(m_TypeRefToMethodTableMap.pTable, rid * sizeof(TADDR));
11244                         // In case this item is also in the hot item subtable, fix it up there as well
11245                         if (hotItemValuePtr != NULL)
11246                         {
11247                             image->ZeroPointerField(m_TypeRefToMethodTableMap.hotItemList,
11248                                 (BYTE *)hotItemValuePtr - (BYTE *)m_TypeRefToMethodTableMap.hotItemList);
11249                         }
11250                     }
11251                 }
11252             }
11253             
11254             rid++;
11255         }
11256         image->EndRegion(CORINFO_REGION_HOT);
11257     }
11258
11259     {
11260         LookupMap<PTR_TypeVarTypeDesc>::Iterator genericParamIter(&m_GenericParamToDescMap);
11261
11262         while (genericParamIter.Next())
11263         {
11264             TypeVarTypeDesc * pTypeDesc = genericParamIter.GetElement();
11265
11266             if (pTypeDesc != NULL)
11267             {
11268                 _ASSERTE(image->IsStored(pTypeDesc));
11269                 pTypeDesc->Fixup(image);
11270             }
11271         }
11272     }
11273
11274     //
11275     // Fixup the assembly reference map table
11276     //
11277
11278     {
11279         LookupMap<PTR_Module>::Iterator manifestModuleIter(&m_ManifestModuleReferencesMap);
11280         DWORD rid = 0;
11281
11282         while (manifestModuleIter.Next())
11283         {
11284             TADDR flags;
11285             Module * pModule = manifestModuleIter.GetElementAndFlags(&flags);
11286
11287             if (pModule != NULL)
11288             {
11289                 if (image->CanEagerBindToModule(pModule))
11290                 {
11291                     if (image->CanHardBindToZapModule(pModule))
11292                     {
11293                         image->FixupField(m_ManifestModuleReferencesMap.pTable, rid * sizeof(TADDR),
11294                             pModule, flags, IMAGE_REL_BASED_RelativePointer);
11295                     }
11296                     else
11297                     {
11298                         image->ZeroPointerField(m_ManifestModuleReferencesMap.pTable, rid * sizeof(TADDR));
11299                     }
11300                 }
11301                 else
11302                 {
11303                     image->ZeroPointerField(m_ManifestModuleReferencesMap.pTable, rid * sizeof(TADDR));
11304                 }
11305             }
11306
11307             rid++;
11308         }
11309     }
11310
11311     //
11312     // Zero out file references table.
11313     //
11314     image->ZeroField(m_FileReferencesMap.pTable, 0,
11315                      m_FileReferencesMap.GetSize() * sizeof(void*));
11316
11317 #ifdef FEATURE_CER
11318     //
11319     // Fixup Constrained Execution Regions restoration records.
11320     //
11321     if (m_pCerNgenRootTable != NULL)
11322     {
11323         image->BeginRegion(CORINFO_REGION_HOT);
11324         image->FixupPointerField(this, offsetof(Module, m_pCerNgenRootTable));
11325         m_pCerNgenRootTable->Fixup(image);
11326         image->EndRegion(CORINFO_REGION_HOT);
11327     }
11328     else
11329         image->ZeroPointerField(this, offsetof(Module, m_pCerNgenRootTable));
11330
11331     // Zero out fields we always compute at runtime lazily.
11332     image->ZeroField(this, offsetof(Module, m_pCerPrepInfo), sizeof(m_pCerPrepInfo));
11333     image->ZeroField(this, offsetof(Module, m_pCerCrst), sizeof(m_pCerCrst));
11334 #endif // FEATURE_CER
11335
11336     image->ZeroField(this, offsetof(Module, m_debuggerSpecificData), sizeof(m_debuggerSpecificData));
11337
11338     image->ZeroField(this, offsetof(Module, m_AssemblyRefByNameCount), sizeof(m_AssemblyRefByNameCount));
11339     image->ZeroPointerField(this, offsetof(Module, m_AssemblyRefByNameTable));
11340
11341     image->ZeroPointerField(this,offsetof(Module, m_NativeMetadataAssemblyRefMap));
11342     
11343     //
11344     // Fixup statics
11345     //
11346     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: fixing up module static data\n"));
11347
11348     image->ZeroPointerField(this, offsetof(Module, m_ModuleID));
11349     image->ZeroField(this, offsetof(Module, m_ModuleIndex), sizeof(m_ModuleIndex));
11350
11351     image->FixupPointerField(this, offsetof(Module, m_pDynamicStaticsInfo));
11352
11353     DynamicStaticsInfo* pDSI = m_pDynamicStaticsInfo;
11354     for (DWORD i = 0; i < m_cDynamicEntries; i++, pDSI++)
11355     {
11356         if (pDSI->pEnclosingMT->GetLoaderModule() == this &&
11357             // CEEPreloader::TriageTypeForZap() could have rejected this type
11358             image->IsStored(pDSI->pEnclosingMT))
11359         {
11360             image->FixupPointerField(m_pDynamicStaticsInfo, (BYTE *)&pDSI->pEnclosingMT - (BYTE *)m_pDynamicStaticsInfo);
11361         }
11362         else
11363         {
11364             // Some other (mutually-recursive) dependency must have loaded
11365             // a generic instantiation whose static were pumped into the
11366             // assembly being ngenned.
11367             image->ZeroPointerField(m_pDynamicStaticsInfo, (BYTE *)&pDSI->pEnclosingMT - (BYTE *)m_pDynamicStaticsInfo);
11368         }
11369     }
11370
11371     // fix up module security descriptor
11372     if (m_pModuleSecurityDescriptor)
11373     {
11374         image->FixupPointerField(this, offsetof(Module, m_pModuleSecurityDescriptor));
11375         m_pModuleSecurityDescriptor->Fixup(image);
11376     }
11377     else
11378     {
11379         image->ZeroPointerField(this, offsetof(Module, m_pModuleSecurityDescriptor));
11380     }
11381
11382     // If we failed to load some types we need to reset the pointers to the static offset tables so they'll be
11383     // rebuilt at runtime.
11384     if (m_pRegularStaticOffsets != (PTR_DWORD)NGEN_STATICS_ALLCLASSES_WERE_LOADED)
11385     {
11386         _ASSERTE(m_pThreadStaticOffsets != (PTR_DWORD)NGEN_STATICS_ALLCLASSES_WERE_LOADED);
11387         image->ZeroPointerField(this, offsetof(Module, m_pRegularStaticOffsets));
11388         image->ZeroPointerField(this, offsetof(Module, m_pThreadStaticOffsets));
11389     }
11390
11391     // Fix up inlining data
11392     if(m_persistentInlineTrackingMap)
11393     {
11394         image->FixupPointerField(this, offsetof(Module, m_persistentInlineTrackingMap));
11395         m_persistentInlineTrackingMap->Fixup(image);
11396     } 
11397     else
11398     {
11399         image->ZeroPointerField(this, offsetof(Module, m_persistentInlineTrackingMap));
11400     }
11401
11402     SetIsModuleSaved();
11403 }
11404 #ifdef _PREFAST_
11405 #pragma warning(pop)
11406 #endif
11407
11408 #endif // FEATURE_NATIVE_IMAGE_GENERATION
11409
11410 #ifdef FEATURE_PREJIT
11411 //
11412 // Is "address" a data-structure in the native image?
11413 //
11414
11415 BOOL Module::IsPersistedObject(void *address)
11416 {
11417     CONTRACTL
11418     {
11419         INSTANCE_CHECK;
11420         NOTHROW;
11421         GC_NOTRIGGER;
11422         MODE_ANY;
11423         FORBID_FAULT;
11424     }
11425     CONTRACTL_END;
11426
11427     if (!HasNativeImage())
11428         return FALSE;
11429
11430     PEImageLayout *pLayout = GetNativeImage();
11431     _ASSERTE(pLayout->IsMapped());
11432
11433     return (address >= pLayout->GetBase()
11434             && address < (BYTE*)pLayout->GetBase() + pLayout->GetVirtualSize());
11435 }
11436
11437 Module *Module::GetModuleFromIndex(DWORD ix)
11438 {
11439     CONTRACT(Module*)
11440     {
11441         INSTANCE_CHECK;
11442         THROWS;
11443         GC_TRIGGERS;
11444         MODE_ANY;
11445         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
11446     }
11447     CONTRACT_END;
11448
11449     if (HasNativeImage())
11450     {
11451         PRECONDITION(GetNativeImage()->CheckNativeImportFromIndex(ix));
11452         CORCOMPILE_IMPORT_TABLE_ENTRY *p = GetNativeImage()->GetNativeImportFromIndex(ix);
11453         RETURN ZapSig::DecodeModuleFromIndexes(this, p->wAssemblyRid, p->wModuleRid);
11454     }
11455     else
11456     {
11457         mdAssemblyRef mdAssemblyRefToken = TokenFromRid(ix, mdtAssemblyRef);
11458         Assembly *pAssembly = this->LookupAssemblyRef(mdAssemblyRefToken);
11459         if (pAssembly)
11460         {
11461             RETURN pAssembly->GetManifestModule();
11462         }
11463         else
11464         {
11465             // GetModuleFromIndex failed
11466             RETURN NULL;
11467         }
11468     }
11469 }
11470 #endif // FEATURE_PREJIT
11471
11472 #endif // !DACCESS_COMPILE
11473
11474 #ifdef FEATURE_PREJIT
11475
11476 Module *Module::GetModuleFromIndexIfLoaded(DWORD ix)
11477 {
11478     CONTRACT(Module*)
11479     {
11480         INSTANCE_CHECK;
11481         NOTHROW;
11482         GC_NOTRIGGER;
11483         MODE_ANY;
11484         PRECONDITION(HasNativeImage());
11485         PRECONDITION(GetNativeImage()->CheckNativeImportFromIndex(ix));
11486         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
11487     }
11488     CONTRACT_END;
11489
11490 #ifndef DACCESS_COMPILE 
11491     CORCOMPILE_IMPORT_TABLE_ENTRY *p = GetNativeImage()->GetNativeImportFromIndex(ix);
11492
11493     RETURN ZapSig::DecodeModuleFromIndexesIfLoaded(this, p->wAssemblyRid, p->wModuleRid);
11494 #else // DACCESS_COMPILE
11495     DacNotImpl();
11496     RETURN NULL;
11497 #endif // DACCESS_COMPILE
11498 }
11499
11500 #ifndef DACCESS_COMPILE 
11501
11502 BYTE *Module::GetNativeFixupBlobData(RVA rva)
11503 {
11504     CONTRACT(BYTE *)
11505     {
11506         INSTANCE_CHECK;
11507         NOTHROW;
11508         GC_NOTRIGGER;
11509         MODE_ANY;
11510         SO_TOLERANT;
11511         POSTCONDITION(CheckPointer(RETVAL));
11512     }
11513     CONTRACT_END;
11514
11515     RETURN (BYTE *) GetNativeOrReadyToRunImage()->GetRvaData(rva);
11516 }
11517
11518 IMDInternalImport *Module::GetNativeAssemblyImport(BOOL loadAllowed)
11519 {
11520     CONTRACT(IMDInternalImport *)
11521     {
11522         INSTANCE_CHECK;
11523         if (loadAllowed) GC_TRIGGERS;                    else GC_NOTRIGGER;
11524         if (loadAllowed) THROWS;                         else NOTHROW;
11525         if (loadAllowed) INJECT_FAULT(COMPlusThrowOM()); else FORBID_FAULT;
11526         MODE_ANY;
11527         PRECONDITION(HasNativeImage());
11528         POSTCONDITION(CheckPointer(RETVAL));
11529     }
11530     CONTRACT_END;
11531
11532     RETURN GetFile()->GetPersistentNativeImage()->GetNativeMDImport(loadAllowed);
11533 }
11534
11535
11536 /*static*/
11537 void Module::RestoreMethodTablePointerRaw(MethodTable ** ppMT,
11538                                           Module *pContainingModule,
11539                                           ClassLoadLevel level)
11540 {
11541     CONTRACTL
11542     {
11543         THROWS;
11544         GC_TRIGGERS;
11545         MODE_ANY;
11546     }
11547     CONTRACTL_END;
11548
11549     // Ensure that the compiler won't fetch the value twice
11550     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppMT);
11551
11552 #ifdef _DEBUG
11553     if (pContainingModule != NULL)
11554     {
11555         Module * dbg_pZapModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppMT));
11556         _ASSERTE((dbg_pZapModule == NULL) || (pContainingModule == dbg_pZapModule));
11557     }
11558 #endif //_DEBUG
11559
11560     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
11561     {
11562 #ifdef _WIN64 
11563         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
11564 #endif
11565
11566         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
11567
11568         if (pContainingModule == NULL)
11569             pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppMT));
11570         PREFIX_ASSUME(pContainingModule != NULL);
11571
11572         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_TYPE_HANDLE);
11573
11574         Module * pInfoModule;
11575         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
11576
11577         TypeHandle  th          = ZapSig::DecodeType(pContainingModule,
11578                                                              pInfoModule,
11579                                                              pBlobData,
11580                                                              level);
11581         *EnsureWritablePages(ppMT) = th.AsMethodTable();
11582     }
11583     else if (*ppMT)
11584     {
11585         ClassLoader::EnsureLoaded(*ppMT, level);
11586     }
11587 }
11588
11589 /*static*/
11590 void Module::RestoreMethodTablePointer(FixupPointer<PTR_MethodTable> * ppMT,
11591                                        Module *pContainingModule,
11592                                        ClassLoadLevel level)
11593 {
11594     CONTRACTL
11595     {
11596         THROWS;
11597         GC_TRIGGERS;
11598         MODE_ANY;
11599     }
11600     CONTRACTL_END;
11601
11602     if (ppMT->IsNull())
11603         return;
11604
11605     if (ppMT->IsTagged())
11606     {
11607         RestoreMethodTablePointerRaw(ppMT->GetValuePtr(), pContainingModule, level);
11608     }
11609     else
11610     {
11611         ClassLoader::EnsureLoaded(ppMT->GetValue(), level);
11612     }
11613 }
11614
11615 /*static*/
11616 void Module::RestoreMethodTablePointer(RelativeFixupPointer<PTR_MethodTable> * ppMT,
11617                                        Module *pContainingModule,
11618                                        ClassLoadLevel level)
11619 {
11620     CONTRACTL
11621     {
11622         THROWS;
11623         GC_TRIGGERS;
11624         MODE_ANY;
11625     }
11626     CONTRACTL_END;
11627
11628     if (ppMT->IsNull())
11629         return;
11630
11631     if (ppMT->IsTagged((TADDR)ppMT))
11632     {
11633         RestoreMethodTablePointerRaw(ppMT->GetValuePtr((TADDR)ppMT), pContainingModule, level);
11634     }
11635     else
11636     {
11637         ClassLoader::EnsureLoaded(ppMT->GetValue((TADDR)ppMT), level);
11638     }
11639 }
11640
11641 #endif // !DACCESS_COMPILE
11642
11643 BOOL Module::IsZappedCode(PCODE code)
11644 {
11645     CONTRACTL
11646     {
11647         NOTHROW;
11648         GC_NOTRIGGER;
11649         SO_TOLERANT;
11650         SUPPORTS_DAC;
11651     }
11652     CONTRACTL_END;
11653
11654     if (!HasNativeImage())
11655         return FALSE;
11656
11657     PEImageLayout *pNativeImage = GetNativeImage();
11658
11659     UINT32 cCode = 0;
11660     PCODE pCodeSection;
11661
11662     pCodeSection = pNativeImage->GetNativeHotCode(&cCode);
11663     if ((pCodeSection <= code) && (code < pCodeSection + cCode))
11664     {
11665         return TRUE;
11666     }
11667
11668     pCodeSection = pNativeImage->GetNativeCode(&cCode);
11669     if ((pCodeSection <= code) && (code < pCodeSection + cCode))
11670     {
11671         return TRUE;
11672     }
11673
11674     return FALSE;
11675 }
11676
11677 BOOL Module::IsZappedPrecode(PCODE code)
11678 {
11679     CONTRACTL
11680     {
11681         NOTHROW;
11682         GC_NOTRIGGER;
11683         SUPPORTS_DAC;
11684         SO_TOLERANT;
11685     }
11686     CONTRACTL_END;
11687
11688     if (m_pNGenLayoutInfo == NULL)
11689         return FALSE;
11690
11691     for (SIZE_T i = 0; i < COUNTOF(m_pNGenLayoutInfo->m_Precodes); i++)
11692     {
11693         if (m_pNGenLayoutInfo->m_Precodes[i].IsInRange(code))
11694             return TRUE;
11695     }
11696
11697     return FALSE;
11698 }
11699
11700 PCCOR_SIGNATURE Module::GetEncodedSig(RVA fixupRva, Module **ppDefiningModule)
11701 {
11702     CONTRACT(PCCOR_SIGNATURE)
11703     {
11704         INSTANCE_CHECK;
11705         THROWS;
11706         GC_TRIGGERS;
11707         MODE_ANY;
11708         SO_INTOLERANT;
11709         POSTCONDITION(CheckPointer(RETVAL));
11710         SUPPORTS_DAC;
11711     }
11712     CONTRACT_END;
11713
11714 #ifndef DACCESS_COMPILE 
11715     PCCOR_SIGNATURE pBuffer = GetNativeFixupBlobData(fixupRva);
11716
11717     BYTE kind = *pBuffer++;
11718
11719     *ppDefiningModule = (kind & ENCODE_MODULE_OVERRIDE) ? GetModuleFromIndex(CorSigUncompressData(pBuffer)) : this;
11720
11721     RETURN pBuffer;
11722 #else
11723     RETURN NULL;
11724 #endif // DACCESS_COMPILE
11725 }
11726
11727 PCCOR_SIGNATURE Module::GetEncodedSigIfLoaded(RVA fixupRva, Module **ppDefiningModule)
11728 {
11729     CONTRACT(PCCOR_SIGNATURE)
11730     {
11731         INSTANCE_CHECK;
11732         NOTHROW;
11733         GC_NOTRIGGER;
11734         MODE_ANY;
11735         SO_INTOLERANT;
11736         POSTCONDITION(CheckPointer(RETVAL));
11737         SUPPORTS_DAC;
11738     }
11739     CONTRACT_END;
11740
11741 #ifndef DACCESS_COMPILE 
11742     PCCOR_SIGNATURE pBuffer = GetNativeFixupBlobData(fixupRva);
11743
11744     BYTE kind = *pBuffer++;
11745
11746     *ppDefiningModule = (kind & ENCODE_MODULE_OVERRIDE) ? GetModuleFromIndexIfLoaded(CorSigUncompressData(pBuffer)) : this;
11747
11748     RETURN pBuffer;
11749 #else
11750     *ppDefiningModule = NULL;
11751     RETURN NULL;
11752 #endif // DACCESS_COMPILE
11753 }
11754
11755 /*static*/
11756 PTR_Module Module::RestoreModulePointerIfLoaded(DPTR(RelativeFixupPointer<PTR_Module>) ppModule, Module *pContainingModule)
11757 {
11758     CONTRACTL
11759     {
11760         NOTHROW;
11761         GC_NOTRIGGER;
11762         MODE_ANY;
11763         FORBID_FAULT;
11764         SUPPORTS_DAC;
11765     }
11766     CONTRACTL_END;
11767
11768     if (!ppModule->IsTagged(dac_cast<TADDR>(ppModule)))
11769         return ppModule->GetValue(dac_cast<TADDR>(ppModule));
11770
11771 #ifndef DACCESS_COMPILE 
11772     PTR_Module * ppValue = ppModule->GetValuePtr(dac_cast<TADDR>(ppModule));
11773
11774     // Ensure that the compiler won't fetch the value twice
11775     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppValue);
11776
11777     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
11778     {
11779
11780 #ifdef _WIN64 
11781         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
11782 #endif
11783
11784         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
11785
11786         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_MODULE_HANDLE);
11787
11788         Module * pInfoModule;
11789         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSigIfLoaded(fixupRva, &pInfoModule);
11790
11791         if (pInfoModule)
11792         {
11793             if (EnsureWritablePagesNoThrow(ppValue, sizeof(*ppValue)))
11794                 *ppValue = pInfoModule;
11795         }
11796         return pInfoModule;
11797     }
11798     else
11799     {
11800         return PTR_Module(fixup);
11801     }
11802 #else
11803     DacNotImpl();
11804     return NULL;
11805 #endif
11806 }
11807
11808 #ifndef DACCESS_COMPILE 
11809
11810 /*static*/
11811 void Module::RestoreModulePointer(RelativeFixupPointer<PTR_Module> * ppModule, Module *pContainingModule)
11812 {
11813     CONTRACTL
11814     {
11815         THROWS;
11816         GC_TRIGGERS;
11817         MODE_ANY;
11818         INJECT_FAULT(COMPlusThrowOM());
11819     }
11820     CONTRACTL_END;
11821
11822     if (!ppModule->IsTagged((TADDR)ppModule))
11823         return;
11824
11825     PTR_Module * ppValue = ppModule->GetValuePtr((TADDR)ppModule);
11826
11827     // Ensure that the compiler won't fetch the value twice
11828     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppValue);
11829
11830     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
11831     {
11832 #ifdef _WIN64 
11833         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
11834 #endif
11835
11836         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
11837
11838         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_MODULE_HANDLE);
11839
11840         Module * pInfoModule;
11841         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
11842
11843         *EnsureWritablePages(ppValue) = pInfoModule;
11844     }
11845 }
11846
11847 /*static*/
11848 void Module::RestoreTypeHandlePointerRaw(TypeHandle *pHandle, Module* pContainingModule, ClassLoadLevel level)
11849 {
11850     CONTRACTL
11851     {
11852         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
11853         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
11854         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else {INJECT_FAULT(COMPlusThrowOM(););}
11855         MODE_ANY;
11856     }
11857     CONTRACTL_END;
11858
11859 #ifdef _DEBUG
11860     if (pContainingModule != NULL)
11861     {
11862         Module * dbg_pZapModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pHandle));
11863         _ASSERTE((dbg_pZapModule == NULL) || (pContainingModule == dbg_pZapModule));
11864     }
11865 #endif //_DEBUG
11866
11867     TADDR fixup;
11868
11869     if (IS_ALIGNED(pHandle, sizeof(TypeHandle)))
11870     {
11871         // Ensure that the compiler won't fetch the value twice
11872         fixup = VolatileLoadWithoutBarrier((TADDR *)pHandle);
11873     }
11874     else
11875     {
11876         // This is necessary to handle in-place fixups (see by FixupTypeHandlePointerInplace)
11877         // in stubs-as-il signatures.
11878
11879         //
11880         // protect this unaligned read with the Module Crst for the rare case that 
11881         // the TypeHandle to fixup is in a signature and unaligned.
11882         //
11883         if (NULL == pContainingModule)
11884         {
11885             pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pHandle));
11886         }
11887         CrstHolder ch(&pContainingModule->m_Crst);
11888         fixup = *(TADDR UNALIGNED *)pHandle;
11889     }
11890
11891     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
11892     {
11893 #ifdef _WIN64 
11894         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
11895 #endif
11896
11897         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
11898
11899         if (NULL == pContainingModule)
11900         {
11901             pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pHandle));
11902         }
11903         PREFIX_ASSUME(pContainingModule != NULL);
11904
11905         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_TYPE_HANDLE);
11906
11907         Module * pInfoModule;
11908         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
11909
11910         TypeHandle thResolved = ZapSig::DecodeType(pContainingModule,
11911                                                            pInfoModule,
11912                                                            pBlobData,
11913                                                            level);
11914         EnsureWritablePages(pHandle);
11915         if (IS_ALIGNED(pHandle, sizeof(TypeHandle)))
11916         {
11917             *pHandle = thResolved;
11918         }
11919         else
11920         {
11921             //
11922             // protect this unaligned write with the Module Crst for the rare case that 
11923             // the TypeHandle to fixup is in a signature and unaligned.
11924             //
11925             CrstHolder ch(&pContainingModule->m_Crst);
11926             *(TypeHandle UNALIGNED *)pHandle = thResolved;
11927         }
11928     }
11929     else if (fixup != NULL)
11930     {
11931         ClassLoader::EnsureLoaded(TypeHandle::FromTAddr(fixup), level);
11932     }
11933 }
11934
11935 /*static*/
11936 void Module::RestoreTypeHandlePointer(FixupPointer<TypeHandle> * pHandle,
11937                                       Module *pContainingModule,
11938                                       ClassLoadLevel level)
11939 {
11940     CONTRACTL
11941     {
11942         THROWS;
11943         GC_TRIGGERS;
11944         MODE_ANY;
11945     }
11946     CONTRACTL_END;
11947
11948     if (pHandle->IsNull())
11949         return;
11950
11951     if (pHandle->IsTagged())
11952     {
11953         RestoreTypeHandlePointerRaw(pHandle->GetValuePtr(), pContainingModule, level);
11954     }
11955     else
11956     {
11957         ClassLoader::EnsureLoaded(pHandle->GetValue(), level);
11958     }
11959 }
11960
11961 /*static*/
11962 void Module::RestoreTypeHandlePointer(RelativeFixupPointer<TypeHandle> * pHandle,
11963                                       Module *pContainingModule,
11964                                       ClassLoadLevel level)
11965 {
11966     CONTRACTL
11967     {
11968         THROWS;
11969         GC_TRIGGERS;
11970         MODE_ANY;
11971     }
11972     CONTRACTL_END;
11973
11974     if (pHandle->IsNull())
11975         return;
11976
11977     if (pHandle->IsTagged((TADDR)pHandle))
11978     {
11979         RestoreTypeHandlePointerRaw(pHandle->GetValuePtr((TADDR)pHandle), pContainingModule, level);
11980     }
11981     else
11982     {
11983         ClassLoader::EnsureLoaded(pHandle->GetValue((TADDR)pHandle), level);
11984     }
11985 }
11986
11987 /*static*/
11988 void Module::RestoreMethodDescPointerRaw(PTR_MethodDesc * ppMD, Module *pContainingModule, ClassLoadLevel level)
11989 {
11990     CONTRACTL
11991     {
11992         THROWS;
11993         GC_TRIGGERS;
11994         MODE_ANY;
11995     }
11996     CONTRACTL_END;
11997
11998     // Ensure that the compiler won't fetch the value twice
11999     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppMD);
12000
12001 #ifdef _DEBUG
12002     if (pContainingModule != NULL)
12003     {
12004         Module * dbg_pZapModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppMD));
12005         _ASSERTE((dbg_pZapModule == NULL) || (pContainingModule == dbg_pZapModule));
12006     }
12007 #endif //_DEBUG
12008
12009     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
12010     {
12011         GCX_PREEMP();
12012
12013 #ifdef _WIN64 
12014         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
12015 #endif
12016
12017         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
12018
12019         if (pContainingModule == NULL)
12020             pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppMD));
12021         PREFIX_ASSUME(pContainingModule != NULL);
12022
12023         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_METHOD_HANDLE);
12024
12025         Module * pInfoModule;
12026         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
12027
12028         *EnsureWritablePages(ppMD) =  ZapSig::DecodeMethod(pContainingModule,
12029                                               pInfoModule,
12030                                               pBlobData);
12031     }
12032     else if (*ppMD) {
12033         (*ppMD)->CheckRestore(level);
12034     }
12035 }
12036
12037 /*static*/
12038 void Module::RestoreMethodDescPointer(FixupPointer<PTR_MethodDesc> * ppMD,
12039                                       Module *pContainingModule,
12040                                       ClassLoadLevel level)
12041 {
12042     CONTRACTL
12043     {
12044         THROWS;
12045         GC_TRIGGERS;
12046         MODE_ANY;
12047     }
12048     CONTRACTL_END;
12049
12050     if (ppMD->IsNull())
12051         return;
12052
12053     if (ppMD->IsTagged())
12054     {
12055         RestoreMethodDescPointerRaw(ppMD->GetValuePtr(), pContainingModule, level);
12056     }
12057     else
12058     {
12059         ppMD->GetValue()->CheckRestore(level);
12060     }
12061 }
12062
12063 /*static*/
12064 void Module::RestoreMethodDescPointer(RelativeFixupPointer<PTR_MethodDesc> * ppMD,
12065                                       Module *pContainingModule,
12066                                       ClassLoadLevel level)
12067 {
12068     CONTRACTL
12069     {
12070         THROWS;
12071         GC_TRIGGERS;
12072         MODE_ANY;
12073     }
12074     CONTRACTL_END;
12075
12076     if (ppMD->IsNull())
12077         return;
12078
12079     if (ppMD->IsTagged((TADDR)ppMD))
12080     {
12081         RestoreMethodDescPointerRaw(ppMD->GetValuePtr((TADDR)ppMD), pContainingModule, level);
12082     }
12083     else
12084     {
12085         ppMD->GetValue((TADDR)ppMD)->CheckRestore(level);
12086     }
12087 }
12088
12089 /*static*/
12090 void Module::RestoreFieldDescPointer(FixupPointer<PTR_FieldDesc> * ppFD)
12091 {
12092     CONTRACTL
12093     {
12094         THROWS;
12095         GC_TRIGGERS;
12096         MODE_ANY;
12097     }
12098     CONTRACTL_END;
12099
12100     PTR_FieldDesc * ppValue = ppFD->GetValuePtr();
12101
12102     // Ensure that the compiler won't fetch the value twice
12103     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppValue);
12104
12105     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
12106     {
12107 #ifdef _WIN64 
12108         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
12109 #endif
12110
12111         Module * pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppValue));
12112         PREFIX_ASSUME(pContainingModule != NULL);
12113
12114         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
12115
12116         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_FIELD_HANDLE);
12117
12118         Module * pInfoModule;
12119         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
12120
12121         *EnsureWritablePages(ppValue) =  ZapSig::DecodeField(pContainingModule,
12122                                                 pInfoModule,
12123                                                 pBlobData);
12124     }
12125 }
12126
12127
12128 //-----------------------------------------------------------------------------
12129
12130 #if 0 
12131
12132         This diagram illustrates the layout of fixups in the ngen image.
12133         This is the case where function foo2 has a class-restore fixup
12134         for class C1 in b.dll.
12135
12136                                   zapBase+curTableVA+rva /         FixupList (see Fixup Encoding below)
12137                                   m_pFixupBlobs
12138                                                             +-------------------+
12139                   pEntry->VA +--------------------+         |     non-NULL      | foo1
12140                              |Handles             |         +-------------------+
12141 ZapHeader.ImportTable        |                    |         |     non-NULL      |
12142                              |                    |         +-------------------+
12143    +------------+            +--------------------+         |     non-NULL      |
12144    |a.dll       |            |Class cctors        |<---+    +-------------------+
12145    |            |            |                    |     \   |         0         |
12146    |            |     p->VA/ |                    |<---+ \  +===================+
12147    |            |      blobs +--------------------+     \ +-------non-NULL      | foo2
12148    +------------+            |Class restore       |      \  +-------------------+
12149    |b.dll       |            |                    |       +-------non-NULL      |
12150    |            |            |                    |         +-------------------+
12151    |  token_C1  |<--------------blob(=>fixedUp/0) |<--pBlob--------index        |
12152    |            | \          |                    |         +-------------------+
12153    |            |  \         +--------------------+         |     non-NULL      |
12154    |            |   \        |                    |         +-------------------+
12155    |            |    \       |        .           |         |         0         |
12156    |            |     \      |        .           |         +===================+
12157    +------------+      \     |        .           |         |         0         | foo3
12158                         \    |                    |         +===================+
12159                          \   +--------------------+         |     non-NULL      | foo4
12160                           \  |Various fixups that |         +-------------------+
12161                            \ |need too happen     |         |         0         |
12162                             \|                    |         +===================+
12163                              |(CorCompileTokenTable)
12164                              |                    |
12165                pEntryEnd->VA +--------------------+
12166
12167
12168
12169 #endif // 0
12170
12171 //-----------------------------------------------------------------------------
12172
12173 BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixupCell)
12174 {
12175     CONTRACTL
12176     {
12177         STANDARD_VM_CHECK;
12178         PRECONDITION(CheckPointer(fixupCell));
12179     }
12180     CONTRACTL_END;
12181
12182     // Ensure that the compiler won't fetch the value twice
12183     SIZE_T fixup = VolatileLoadWithoutBarrier(fixupCell);
12184
12185     if (pSection->Signatures != NULL)
12186     {
12187         if (fixup == NULL)
12188         {
12189             PTR_DWORD pSignatures = dac_cast<PTR_DWORD>(GetNativeOrReadyToRunImage()->GetRvaData(pSection->Signatures));
12190
12191             if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell))
12192                 return FALSE;
12193
12194             _ASSERTE(*fixupCell != NULL);
12195         }
12196     }
12197     else
12198     {
12199         if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection))
12200         {
12201             // Fixup has not been fixed up yet
12202             if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell))
12203                 return FALSE;
12204
12205             _ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection));
12206         }
12207         else
12208         {
12209             //
12210             // Handle tables are special. We may need to restore static handle or previous 
12211             // attempts to load handle could have been partial.
12212             //
12213             if (pSection->Type == CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE)
12214             {
12215                 TypeHandle::FromPtr((void *)fixup).CheckRestore();
12216             }
12217             else
12218             if (pSection->Type == CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE)
12219             {
12220                 ((MethodDesc *)(fixup))->CheckRestore();
12221             }
12222         }
12223     }
12224
12225     return TRUE;
12226 }
12227
12228 //-----------------------------------------------------------------------------
12229
12230 void Module::RunEagerFixups()
12231 {
12232     STANDARD_VM_CONTRACT;
12233
12234     COUNT_T nSections;
12235     PTR_CORCOMPILE_IMPORT_SECTION pSections = GetImportSections(&nSections);
12236
12237     if (nSections == 0)
12238         return;
12239
12240 #ifdef _DEBUG
12241     // Loading types during eager fixup is not a tested scenario. Make bugs out of any attempts to do so in a
12242     // debug build. Use holder to recover properly in case of exception.
12243     class ForbidTypeLoadHolder
12244     {
12245     public:
12246         ForbidTypeLoadHolder()
12247         {
12248             BEGIN_FORBID_TYPELOAD();
12249         }
12250
12251         ~ForbidTypeLoadHolder()
12252         {
12253             END_FORBID_TYPELOAD();
12254         }
12255     }
12256     forbidTypeLoad;
12257 #endif
12258
12259     // TODO: Verify that eager fixup dependency graphs can contain no cycles
12260     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
12261
12262     PEImageLayout *pNativeImage = GetNativeOrReadyToRunImage();
12263
12264     for (COUNT_T iSection = 0; iSection < nSections; iSection++)
12265     {
12266         PTR_CORCOMPILE_IMPORT_SECTION pSection = pSections + iSection;
12267
12268         if ((pSection->Flags & CORCOMPILE_IMPORT_FLAGS_EAGER) == 0)
12269             continue;
12270
12271         COUNT_T tableSize;
12272         TADDR tableBase = pNativeImage->GetDirectoryData(&pSection->Section, &tableSize);
12273
12274         if (pSection->Signatures != NULL)
12275         {
12276             PTR_DWORD pSignatures = dac_cast<PTR_DWORD>(pNativeImage->GetRvaData(pSection->Signatures));
12277
12278             for (SIZE_T * fixupCell = (SIZE_T *)tableBase; fixupCell < (SIZE_T *)(tableBase + tableSize); fixupCell++)
12279             {
12280                 SIZE_T fixupIndex = fixupCell - (SIZE_T *)tableBase;
12281                 if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell))
12282                 {
12283                     _ASSERTE(!"LoadDynamicInfoEntry failed");
12284                     ThrowHR(COR_E_BADIMAGEFORMAT);
12285                 }
12286                 _ASSERTE(*fixupCell != NULL);
12287             }
12288         }
12289         else
12290         {
12291             for (SIZE_T * fixupCell = (SIZE_T *)tableBase; fixupCell < (SIZE_T *)(tableBase + tableSize); fixupCell++)
12292             {
12293                 // Ensure that the compiler won't fetch the value twice
12294                 SIZE_T fixup = VolatileLoadWithoutBarrier(fixupCell);
12295
12296                 // This method may execute multiple times in multi-domain scenarios. Check that the fixup has not been 
12297                 // fixed up yet.
12298                 if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection))
12299                 {
12300                     if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell))
12301                     {
12302                         _ASSERTE(!"LoadDynamicInfoEntry failed");
12303                         ThrowHR(COR_E_BADIMAGEFORMAT);
12304                     }
12305                     _ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection));
12306                 }
12307             }
12308         }
12309     }
12310 }
12311
12312 void Module::LoadTokenTables()
12313 {
12314     CONTRACTL
12315     {
12316         INSTANCE_CHECK;
12317         THROWS;
12318         GC_TRIGGERS;
12319         MODE_ANY;
12320         PRECONDITION(HasNativeImage());
12321     }
12322     CONTRACTL_END;
12323
12324 #ifndef CROSSGEN_COMPILE
12325     if (NingenEnabled())
12326         return;
12327
12328     CORCOMPILE_EE_INFO_TABLE *pEEInfo = GetNativeImage()->GetNativeEEInfoTable();
12329     PREFIX_ASSUME(pEEInfo != NULL);
12330
12331     pEEInfo->inlinedCallFrameVptr = InlinedCallFrame::GetMethodFrameVPtr();
12332     pEEInfo->addrOfCaptureThreadGlobal = (LONG *)&g_TrapReturningThreads;
12333
12334     //CoreClr doesn't always have the debugger loaded
12335     //patch up the ngen image to point to this address so that the JIT bypasses JMC if there is no debugger
12336     static DWORD g_dummyJMCFlag = 0;
12337     pEEInfo->addrOfJMCFlag = g_pDebugInterface ? g_pDebugInterface->GetJMCFlagAddr(this) : &g_dummyJMCFlag;
12338    
12339     pEEInfo->gsCookie = GetProcessGSCookie();
12340
12341     if (!IsSystem())
12342     {
12343         pEEInfo->emptyString = (CORINFO_Object **)StringObject::GetEmptyStringRefPtr();
12344     }
12345
12346 #ifdef FEATURE_IMPLICIT_TLS
12347     pEEInfo->threadTlsIndex = TLS_OUT_OF_INDEXES;
12348 #else
12349     pEEInfo->threadTlsIndex = GetThreadTLSIndex();
12350 #endif
12351     pEEInfo->rvaStaticTlsIndex = NULL;
12352 #endif // CROSSGEN_COMPILE
12353 }
12354
12355 #endif // !DACCESS_COMPILE
12356
12357 // Returns the RVA to the compressed debug information blob for the given method
12358
12359 CORCOMPILE_DEBUG_ENTRY Module::GetMethodDebugInfoOffset(MethodDesc *pMD)
12360 {
12361     CONTRACT(CORCOMPILE_DEBUG_ENTRY)
12362     {
12363         INSTANCE_CHECK;
12364         PRECONDITION(HasNativeImage());
12365         PRECONDITION(CheckPointer(pMD) && pMD->IsPreImplemented());
12366         POSTCONDITION(GetNativeImage()->CheckRva(RETVAL, NULL_OK));
12367         NOTHROW;
12368         GC_NOTRIGGER;
12369         MODE_ANY;
12370         SUPPORTS_DAC;
12371     }
12372     CONTRACT_END;
12373
12374     if (!GetNativeImage()->HasNativeDebugMap() || pMD->IsRuntimeSupplied())
12375         RETURN 0;
12376
12377     COUNT_T size;
12378     PTR_CORCOMPILE_DEBUG_RID_ENTRY ridTable = 
12379         dac_cast<PTR_CORCOMPILE_DEBUG_RID_ENTRY>(GetNativeImage()->GetNativeDebugMap(&size));
12380
12381     COUNT_T count = size / sizeof(CORCOMPILE_DEBUG_RID_ENTRY);
12382     // The size should be odd for better hashing
12383     _ASSERTE((count & 1) != 0);
12384
12385     CORCOMPILE_DEBUG_RID_ENTRY ridEntry = ridTable[GetDebugRidEntryHash(pMD->GetMemberDef()) % count];
12386
12387     // Do we have multiple code corresponding to the same RID
12388     if (!IsMultipleLabelledEntries(ridEntry))
12389     {
12390         RETURN(ridEntry);
12391     }
12392
12393     PTR_CORCOMPILE_DEBUG_LABELLED_ENTRY pLabelledEntry =
12394         PTR_CORCOMPILE_DEBUG_LABELLED_ENTRY
12395         (GetNativeImage()->GetRvaData(ridEntry &
12396                                       ~CORCOMPILE_DEBUG_MULTIPLE_ENTRIES));
12397
12398     DWORD codeRVA = GetNativeImage()->
12399         GetDataRva((const TADDR)pMD->GetNativeCode());
12400 #if defined(_TARGET_ARM_)
12401     // Since the Thumb Bit is set on ARM, the RVA calculated above will have it set as well
12402     // and will result in the failure of checks in the loop below. Hence, mask off the
12403     // bit before proceeding ahead.
12404     codeRVA = ThumbCodeToDataPointer<DWORD, DWORD>(codeRVA);
12405 #endif // _TARGET_ARM_
12406
12407     for (;;)
12408     {
12409         if (pLabelledEntry->nativeCodeRVA == codeRVA)
12410         {
12411             RETURN (pLabelledEntry->debugInfoOffset & ~CORCOMPILE_DEBUG_MULTIPLE_ENTRIES);
12412         }
12413
12414         if (!IsMultipleLabelledEntries(pLabelledEntry->debugInfoOffset))
12415         {
12416             break;
12417         }
12418
12419         pLabelledEntry++;
12420     }
12421
12422     _ASSERTE(!"Debug info not found - corrupted ngen image?");
12423     RETURN (0);
12424 }
12425
12426 PTR_BYTE Module::GetNativeDebugInfo(MethodDesc * pMD)
12427 {
12428     CONTRACTL
12429     {
12430         INSTANCE_CHECK;
12431         PRECONDITION(HasNativeImage());
12432         PRECONDITION(CheckPointer(pMD));
12433         PRECONDITION(pMD->GetZapModule() == this);
12434         THROWS;
12435         GC_NOTRIGGER;
12436         MODE_ANY;
12437         SUPPORTS_DAC;
12438     }
12439     CONTRACTL_END;
12440
12441     CORCOMPILE_DEBUG_ENTRY debugInfoOffset = GetMethodDebugInfoOffset(pMD);
12442
12443     if (debugInfoOffset == 0)
12444         return NULL;
12445
12446     return dac_cast<PTR_BYTE>(GetNativeImage()->GetRvaData(debugInfoOffset));
12447 }
12448 #endif //FEATURE_PREJIT
12449
12450
12451
12452 #ifndef DACCESS_COMPILE 
12453
12454 #ifdef FEATURE_PREJIT 
12455 //
12456 // Profile data management
12457 //
12458
12459 ICorJitInfo::ProfileBuffer * Module::AllocateProfileBuffer(mdToken _token, DWORD _count, DWORD _ILSize)
12460 {
12461     CONTRACT (ICorJitInfo::ProfileBuffer*)
12462     {
12463         INSTANCE_CHECK;
12464         THROWS;
12465         GC_NOTRIGGER;
12466         MODE_ANY;
12467         INJECT_FAULT(CONTRACT_RETURN NULL;);
12468         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
12469     }
12470     CONTRACT_END;
12471
12472     assert(_ILSize != 0);
12473
12474     DWORD   listSize   = sizeof(CORCOMPILE_METHOD_PROFILE_LIST);
12475     DWORD   headerSize = sizeof(CORBBTPROF_METHOD_HEADER);
12476     DWORD   blockSize  = _count * sizeof(CORBBTPROF_BLOCK_DATA);
12477     DWORD   totalSize  = listSize + headerSize + blockSize;
12478
12479     BYTE *  memory     = (BYTE *) (void *) this->m_pAssembly->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(totalSize));
12480
12481     CORCOMPILE_METHOD_PROFILE_LIST * methodProfileList = (CORCOMPILE_METHOD_PROFILE_LIST *) (memory + 0);
12482     CORBBTPROF_METHOD_HEADER *       methodProfileData = (CORBBTPROF_METHOD_HEADER *)       (memory + listSize);
12483     
12484     // Note: Memory allocated on the LowFrequencyHeap is zero filled
12485
12486     methodProfileData->size          = headerSize + blockSize;
12487     methodProfileData->method.token  = _token;
12488     methodProfileData->method.ILSize = _ILSize;
12489     methodProfileData->method.cBlock = _count;
12490
12491     assert(methodProfileData->size == methodProfileData->Size());
12492
12493     // Link it to the per module list of profile data buffers
12494
12495     methodProfileList->next = m_methodProfileList;
12496     m_methodProfileList     = methodProfileList;
12497
12498     RETURN ((ICorJitInfo::ProfileBuffer *) &methodProfileData->method.block[0]);
12499 }
12500
12501 HANDLE Module::OpenMethodProfileDataLogFile(GUID mvid)
12502 {
12503     CONTRACTL
12504     {
12505         INSTANCE_CHECK;
12506         THROWS;
12507         GC_NOTRIGGER;
12508         MODE_ANY;
12509     }
12510     CONTRACTL_END;
12511
12512     HANDLE profileDataFile = INVALID_HANDLE_VALUE;
12513
12514     SString path;
12515     LPCWSTR assemblyPath = m_file->GetPath();
12516     LPCWSTR ibcDir = g_pConfig->GetZapBBInstrDir();     // should we put the ibc data into a particular directory?
12517     if (ibcDir == 0) {
12518         path.Set(assemblyPath);                         // no, then put it beside the IL dll
12519     }
12520     else {
12521         LPCWSTR assemblyFileName = wcsrchr(assemblyPath, '\\'); 
12522         if (assemblyFileName)
12523             assemblyFileName++;                         // skip past the \ char
12524         else 
12525             assemblyFileName = assemblyPath;
12526
12527         path.Set(ibcDir);                               // yes, put it in the directory, named with the assembly name.
12528         path.Append('\\');
12529         path.Append(assemblyFileName);
12530     }
12531
12532     SString::Iterator ext = path.End();                 // remove the extension
12533     if (path.FindBack(ext, '.'))
12534         path.Truncate(ext);
12535     path.Append(W(".ibc"));               // replace with .ibc extension
12536
12537     profileDataFile = WszCreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
12538                                     OPEN_ALWAYS,
12539                                     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
12540                                     NULL);
12541
12542     if (profileDataFile == INVALID_HANDLE_VALUE) COMPlusThrowWin32();
12543
12544     DWORD count;
12545     CORBBTPROF_FILE_HEADER fileHeader;
12546
12547     SetFilePointer(profileDataFile, 0, NULL, FILE_BEGIN);
12548     BOOL result = ReadFile(profileDataFile, &fileHeader, sizeof(fileHeader), &count, NULL);
12549     if (result                                                    &&
12550         (count                 == sizeof(fileHeader))             &&
12551         (fileHeader.HeaderSize == sizeof(CORBBTPROF_FILE_HEADER)) &&
12552         (fileHeader.Magic      == CORBBTPROF_MAGIC)               &&
12553         (fileHeader.Version    == CORBBTPROF_CURRENT_VERSION)     &&
12554         (fileHeader.MVID       == mvid))
12555     {
12556         //
12557         // The existing file was from the same assembly version - just append to it.
12558         //
12559
12560         SetFilePointer(profileDataFile, 0, NULL, FILE_END);
12561     }
12562     else
12563     {
12564         //
12565         // Either this is a new file, or it's from a previous version.  Replace the contents.
12566         //
12567
12568         SetFilePointer(profileDataFile, 0, NULL, FILE_BEGIN);
12569     }
12570
12571     return profileDataFile;
12572 }
12573
12574 // Note that this method cleans up the profile buffers, so it's crucial that
12575 // no managed code in the module is allowed to run once this method has
12576 // been called!
12577
12578 class ProfileMap
12579 {
12580 public:
12581     SIZE_T getCurrentOffset() {WRAPPER_NO_CONTRACT; return buffer.Size();}
12582
12583     void * getOffsetPtr(SIZE_T offset)
12584     {
12585         LIMITED_METHOD_CONTRACT;
12586         _ASSERTE(offset <= buffer.Size());
12587         return ((void *) (((char *) buffer.Ptr()) + offset));
12588     }
12589
12590     void *Allocate(SIZE_T size)
12591     {
12592         CONTRACT(void *)
12593         {
12594             INSTANCE_CHECK;
12595             THROWS;
12596             GC_NOTRIGGER;
12597             MODE_ANY;
12598             INJECT_FAULT(CONTRACT_RETURN NULL;);
12599             POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
12600         }
12601         CONTRACT_END;
12602
12603         SIZE_T oldSize = buffer.Size();
12604         buffer.ReSizeThrows(oldSize + size);
12605         RETURN getOffsetPtr(oldSize);
12606     }
12607
12608 private:
12609     CQuickBytes buffer;
12610 };
12611
12612 class ProfileEmitter
12613 {
12614 public:
12615
12616     ProfileEmitter()
12617     {
12618         LIMITED_METHOD_CONTRACT;
12619         pSectionList = NULL;
12620     }
12621
12622     ~ProfileEmitter()
12623     {
12624         WRAPPER_NO_CONTRACT;
12625         while (pSectionList)
12626         {
12627             SectionList *temp = pSectionList->next;
12628             delete pSectionList;
12629             pSectionList = temp;
12630         }
12631     }
12632
12633     ProfileMap *EmitNewSection(SectionFormat format)
12634     {
12635         WRAPPER_NO_CONTRACT;
12636         SectionList *s = new SectionList();
12637
12638         s->format    = format;
12639         s->next      = pSectionList;
12640         pSectionList = s;
12641
12642         return &s->profileMap;
12643     }
12644
12645     //
12646     // Serialize the profile sections into pMap
12647     //
12648
12649     void Serialize(ProfileMap *profileMap, GUID mvid)
12650     {
12651         CONTRACTL
12652         {
12653             INSTANCE_CHECK;
12654             THROWS;
12655             GC_NOTRIGGER;
12656             MODE_ANY;
12657             INJECT_FAULT(COMPlusThrowOM());
12658         }
12659         CONTRACTL_END;
12660
12661         //
12662         // Allocate the file header
12663         //
12664         {
12665             CORBBTPROF_FILE_HEADER *fileHeader;
12666             fileHeader = (CORBBTPROF_FILE_HEADER *) profileMap->Allocate(sizeof(CORBBTPROF_FILE_HEADER));
12667             
12668             fileHeader->HeaderSize = sizeof(CORBBTPROF_FILE_HEADER);
12669             fileHeader->Magic      = CORBBTPROF_MAGIC;
12670             fileHeader->Version    = CORBBTPROF_CURRENT_VERSION;
12671             fileHeader->MVID       = mvid;
12672         }
12673
12674         //
12675         // Count the number of sections
12676         //
12677         ULONG32 numSections = 0;
12678         for (SectionList *p = pSectionList; p; p = p->next)
12679         {
12680             numSections++;
12681         }
12682
12683         //
12684         // Allocate the section table
12685         //
12686         SIZE_T tableEntryOffset;
12687         {
12688             CORBBTPROF_SECTION_TABLE_HEADER *tableHeader;
12689             tableHeader = (CORBBTPROF_SECTION_TABLE_HEADER *)
12690                 profileMap->Allocate(sizeof(CORBBTPROF_SECTION_TABLE_HEADER));
12691
12692             tableHeader->NumEntries = numSections;
12693             tableEntryOffset = profileMap->getCurrentOffset();
12694             
12695             CORBBTPROF_SECTION_TABLE_ENTRY *tableEntry;
12696             tableEntry = (CORBBTPROF_SECTION_TABLE_ENTRY *)
12697                 profileMap->Allocate(sizeof(CORBBTPROF_SECTION_TABLE_ENTRY) * numSections);
12698         }
12699
12700         //
12701         // Allocate the data sections
12702         //
12703         {
12704             ULONG secCount = 0;
12705             for (SectionList *pSec = pSectionList; pSec; pSec = pSec->next, secCount++)
12706             {
12707                 SIZE_T offset = profileMap->getCurrentOffset();
12708                 assert((offset & 0x3) == 0);
12709                 
12710                 SIZE_T actualSize  = pSec->profileMap.getCurrentOffset();
12711                 SIZE_T alignUpSize = AlignUp(actualSize, sizeof(DWORD));
12712                 
12713                 profileMap->Allocate(alignUpSize);
12714                 
12715                 memcpy(profileMap->getOffsetPtr(offset), pSec->profileMap.getOffsetPtr(0), actualSize);
12716                 if (alignUpSize > actualSize)
12717                 {
12718                     memset(((BYTE*)profileMap->getOffsetPtr(offset))+actualSize, 0, (alignUpSize - actualSize)); 
12719                 }
12720                 
12721                 CORBBTPROF_SECTION_TABLE_ENTRY *tableEntry;
12722                 tableEntry = (CORBBTPROF_SECTION_TABLE_ENTRY *) profileMap->getOffsetPtr(tableEntryOffset);
12723                 tableEntry += secCount;
12724                 tableEntry->FormatID    = pSec->format;
12725                 tableEntry->Data.Offset = offset;
12726                 tableEntry->Data.Size   = alignUpSize;
12727             }
12728         }
12729
12730         //
12731         // Allocate the end token marker
12732         //
12733         {
12734             ULONG *endToken;
12735             endToken = (ULONG *) profileMap->Allocate(sizeof(ULONG));
12736             
12737             *endToken = CORBBTPROF_END_TOKEN;
12738         }
12739     }
12740
12741 private:
12742     struct SectionList
12743     {
12744         SectionFormat format;
12745         ProfileMap    profileMap;
12746         SectionList   *next;
12747     };
12748     SectionList *  pSectionList;
12749 };
12750
12751
12752 /*static*/ idTypeSpec          TypeSpecBlobEntry::s_lastTypeSpecToken                   = idTypeSpecNil;
12753 /*static*/ idMethodSpec        MethodSpecBlobEntry::s_lastMethodSpecToken               = idMethodSpecNil;
12754 /*static*/ idExternalNamespace ExternalNamespaceBlobEntry::s_lastExternalNamespaceToken = idExternalNamespaceNil;
12755 /*static*/ idExternalType      ExternalTypeBlobEntry::s_lastExternalTypeToken           = idExternalTypeNil;
12756 /*static*/ idExternalSignature ExternalSignatureBlobEntry::s_lastExternalSignatureToken = idExternalSignatureNil;
12757 /*static*/ idExternalMethod    ExternalMethodBlobEntry::s_lastExternalMethodToken       = idExternalMethodNil;
12758
12759
12760 inline static size_t HashCombine(size_t h1, size_t h2)
12761 {
12762     LIMITED_METHOD_CONTRACT;
12763
12764     size_t result = (h1 * 129) ^ h2;
12765     return result;
12766 }
12767
12768 bool        TypeSpecBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
12769 {
12770     WRAPPER_NO_CONTRACT;
12771
12772     if (this->kind() != other->kind())
12773         return false;
12774
12775     const TypeSpecBlobEntry *  other2 = static_cast<const TypeSpecBlobEntry *>(other);
12776
12777     if (this->cbSig() != other2->cbSig())
12778         return false;
12779
12780     PCCOR_SIGNATURE  p1 = this->pSig();
12781     PCCOR_SIGNATURE  p2 = other2->pSig();
12782     
12783     for (DWORD i=0; (i < this->cbSig()); i++)
12784         if (p1[i] != p2[i])
12785             return false;
12786
12787     return true;
12788 }
12789
12790 size_t     TypeSpecBlobEntry::Hash() const
12791 {
12792     WRAPPER_NO_CONTRACT;
12793
12794     size_t hashValue = HashInit();
12795
12796     PCCOR_SIGNATURE  p1 = pSig();
12797     for (DWORD i=0; (i < cbSig()); i++)
12798         hashValue = HashCombine(hashValue, p1[i]);
12799
12800     return hashValue;
12801 }
12802
12803 TypeSpecBlobEntry::TypeSpecBlobEntry(DWORD _cbSig, PCCOR_SIGNATURE _pSig)
12804 {
12805     CONTRACTL
12806     {
12807         NOTHROW;
12808         GC_NOTRIGGER;
12809         PRECONDITION(_cbSig > 0);
12810         PRECONDITION(CheckPointer(_pSig));
12811     }
12812     CONTRACTL_END;
12813
12814     m_token  = idTypeSpecNil;
12815     m_flags  = 0;
12816     m_cbSig  = 0;
12817
12818     COR_SIGNATURE * pNewSig = (COR_SIGNATURE *) new (nothrow) BYTE[_cbSig];
12819     if (pNewSig != NULL)
12820     {
12821         m_flags  = 0;
12822         m_cbSig  = _cbSig;
12823         memcpy(pNewSig, _pSig, _cbSig);
12824     }
12825     m_pSig = const_cast<PCCOR_SIGNATURE>(pNewSig);
12826 }
12827
12828 /* static */ const TypeSpecBlobEntry *  TypeSpecBlobEntry::FindOrAdd(PTR_Module      pModule, 
12829                                                                      DWORD           _cbSig, 
12830                                                                      PCCOR_SIGNATURE _pSig)
12831 {
12832     CONTRACTL
12833     {
12834         NOTHROW;
12835         GC_NOTRIGGER;
12836     }
12837     CONTRACTL_END;
12838
12839     if ((_cbSig == 0) || (_pSig == NULL))
12840         return NULL;
12841
12842     TypeSpecBlobEntry sEntry(_cbSig, _pSig);
12843
12844     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
12845     if (pEntry == NULL)
12846     {
12847         //
12848         // Not Found, add a new type spec profiling blob entry
12849         // 
12850         TypeSpecBlobEntry * newEntry = new (nothrow) TypeSpecBlobEntry(_cbSig, _pSig);
12851         if (newEntry == NULL)
12852             return NULL;
12853
12854         newEntry->newToken();                 // Assign a new ibc type spec token
12855         CONTRACT_VIOLATION(ThrowsViolation);
12856         pModule->GetProfilingBlobTable()->Add(newEntry);
12857         pEntry = newEntry;
12858     }
12859
12860     //
12861     // Return the type spec entry that we found or the new one that we just created
12862     // 
12863     _ASSERTE(pEntry->kind() == ParamTypeSpec);
12864     return static_cast<const TypeSpecBlobEntry *>(pEntry);
12865 }
12866
12867 bool        MethodSpecBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
12868 {
12869     WRAPPER_NO_CONTRACT;
12870
12871     if (this->kind() != other->kind())
12872         return false;
12873
12874     const MethodSpecBlobEntry *  other2 = static_cast<const MethodSpecBlobEntry *>(other);
12875
12876     if (this->cbSig() != other2->cbSig())
12877         return false;
12878
12879     PCCOR_SIGNATURE  p1 = this->pSig();
12880     PCCOR_SIGNATURE  p2 = other2->pSig();
12881     
12882     for (DWORD i=0; (i < this->cbSig()); i++)
12883         if (p1[i] != p2[i])
12884             return false;
12885
12886     return true;
12887 }
12888
12889 size_t     MethodSpecBlobEntry::Hash() const
12890 {
12891     WRAPPER_NO_CONTRACT;
12892
12893     size_t hashValue = HashInit();
12894
12895     PCCOR_SIGNATURE  p1 = pSig();
12896     for (DWORD i=0; (i < cbSig()); i++)
12897         hashValue = HashCombine(hashValue, p1[i]);
12898
12899     return hashValue;
12900 }
12901
12902 MethodSpecBlobEntry::MethodSpecBlobEntry(DWORD _cbSig, PCCOR_SIGNATURE _pSig)
12903 {
12904     CONTRACTL
12905     {
12906         NOTHROW;
12907         GC_NOTRIGGER;
12908         PRECONDITION(_cbSig > 0);
12909         PRECONDITION(CheckPointer(_pSig));
12910     }
12911     CONTRACTL_END;
12912
12913     m_token  = idMethodSpecNil;
12914     m_flags  = 0;
12915     m_cbSig  = 0;
12916
12917     COR_SIGNATURE * pNewSig = (COR_SIGNATURE *) new (nothrow) BYTE[_cbSig];
12918     if (pNewSig != NULL)
12919     {
12920         m_flags  = 0;
12921         m_cbSig  = _cbSig;
12922         memcpy(pNewSig, _pSig, _cbSig);
12923     }
12924     m_pSig = const_cast<PCCOR_SIGNATURE>(pNewSig);
12925 }
12926
12927 /* static */ const MethodSpecBlobEntry *  MethodSpecBlobEntry::FindOrAdd(PTR_Module      pModule, 
12928                                                                          DWORD           _cbSig, 
12929                                                                          PCCOR_SIGNATURE _pSig)
12930 {
12931     CONTRACTL
12932     {
12933         NOTHROW;
12934         GC_NOTRIGGER;
12935     }
12936     CONTRACTL_END;
12937
12938     if ((_cbSig == 0) || (_pSig == NULL))
12939         return NULL;
12940
12941     MethodSpecBlobEntry sEntry(_cbSig, _pSig);
12942
12943     const ProfilingBlobEntry * pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
12944     if (pEntry == NULL)
12945     {
12946         //
12947         // Not Found, add a new method spec profiling blob entry
12948         // 
12949         MethodSpecBlobEntry * newEntry = new (nothrow) MethodSpecBlobEntry(_cbSig, _pSig);
12950         if (newEntry == NULL)
12951             return NULL;
12952
12953         newEntry->newToken();                 // Assign a new ibc method spec token
12954         CONTRACT_VIOLATION(ThrowsViolation);
12955         pModule->GetProfilingBlobTable()->Add(newEntry);
12956         pEntry = newEntry;
12957     }
12958
12959     //
12960     // Return the method spec entry that we found or the new one that we just created
12961     // 
12962     _ASSERTE(pEntry->kind() == ParamMethodSpec);
12963     return static_cast<const MethodSpecBlobEntry *>(pEntry);
12964 }
12965
12966 bool        ExternalNamespaceBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
12967 {
12968     WRAPPER_NO_CONTRACT;
12969
12970     if (this->kind() != other->kind())
12971         return false;
12972
12973     const ExternalNamespaceBlobEntry *  other2 = static_cast<const ExternalNamespaceBlobEntry *>(other);
12974
12975     if (this->cbName() != other2->cbName())
12976         return false;
12977
12978     LPCSTR p1 = this->pName();
12979     LPCSTR p2 = other2->pName();
12980     
12981     for (DWORD i=0; (i < this->cbName()); i++)
12982         if (p1[i] != p2[i])
12983             return false;
12984
12985     return true;
12986 }
12987
12988 size_t     ExternalNamespaceBlobEntry::Hash() const
12989 {
12990     WRAPPER_NO_CONTRACT;
12991
12992     size_t hashValue = HashInit();
12993
12994     LPCSTR p1 = pName();
12995     for (DWORD i=0; (i < cbName()); i++)
12996         hashValue = HashCombine(hashValue, p1[i]);
12997
12998     return hashValue;
12999 }
13000
13001 ExternalNamespaceBlobEntry::ExternalNamespaceBlobEntry(LPCSTR _pName)
13002 {
13003    CONTRACTL
13004     {
13005         NOTHROW;
13006         GC_NOTRIGGER;
13007         PRECONDITION(CheckPointer(_pName));
13008     }
13009     CONTRACTL_END;
13010
13011     m_token  = idExternalNamespaceNil;
13012     m_cbName = 0;
13013     m_pName  = NULL;
13014
13015     DWORD _cbName = (DWORD) strlen(_pName) + 1;
13016     LPSTR * pName = (LPSTR *) new (nothrow) CHAR[_cbName];
13017     if (pName != NULL)
13018     {
13019         m_cbName = _cbName;
13020         memcpy(pName, _pName, _cbName);
13021         m_pName  = (LPCSTR) pName;
13022     }
13023 }
13024
13025 /* static */ const ExternalNamespaceBlobEntry *  ExternalNamespaceBlobEntry::FindOrAdd(PTR_Module pModule, LPCSTR _pName)
13026 {
13027    CONTRACTL
13028     {
13029         NOTHROW;
13030         GC_NOTRIGGER;
13031     }
13032     CONTRACTL_END;
13033
13034     if ((_pName == NULL) || (::strlen(_pName) == 0))
13035         return NULL;
13036
13037     ExternalNamespaceBlobEntry sEntry(_pName);
13038
13039     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
13040     if (pEntry == NULL)
13041     {
13042         //
13043         // Not Found, add a new external namespace blob entry
13044         // 
13045         ExternalNamespaceBlobEntry * newEntry = new (nothrow) ExternalNamespaceBlobEntry(_pName);
13046         if (newEntry == NULL)
13047             return NULL;
13048
13049         newEntry->newToken();                 // Assign a new ibc external namespace token
13050         CONTRACT_VIOLATION(ThrowsViolation);
13051         pModule->GetProfilingBlobTable()->Add(newEntry);
13052         pEntry = newEntry;
13053     }
13054
13055     //
13056     // Return the external namespace entry that we found or the new one that we just created
13057     // 
13058     _ASSERTE(pEntry->kind() == ExternalNamespaceDef);
13059     return static_cast<const ExternalNamespaceBlobEntry *>(pEntry);
13060 }
13061
13062 bool        ExternalTypeBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
13063 {
13064     WRAPPER_NO_CONTRACT;
13065
13066     if (this->kind() != other->kind())
13067         return false;
13068
13069     const ExternalTypeBlobEntry *  other2 = static_cast<const ExternalTypeBlobEntry *>(other);
13070
13071     if (this->assemblyRef() != other2->assemblyRef())
13072         return false;
13073
13074     if (this->nestedClass() != other2->nestedClass())
13075         return false;
13076
13077     if (this->nameSpace() != other2->nameSpace())
13078         return false;
13079
13080     if (this->cbName() != other2->cbName())
13081         return false;
13082
13083     LPCSTR p1 = this->pName();
13084     LPCSTR p2 = other2->pName();
13085     
13086     for (DWORD i=0; (i < this->cbName()); i++)
13087         if (p1[i] != p2[i])
13088             return false;
13089
13090     return true;
13091 }
13092
13093 size_t     ExternalTypeBlobEntry::Hash() const
13094 {
13095     WRAPPER_NO_CONTRACT;
13096
13097     size_t hashValue = HashInit();
13098
13099     hashValue = HashCombine(hashValue, assemblyRef());
13100     hashValue = HashCombine(hashValue, nestedClass());
13101     hashValue = HashCombine(hashValue, nameSpace());
13102
13103     LPCSTR p1 = pName();
13104     
13105     for (DWORD i=0; (i < cbName()); i++)
13106         hashValue = HashCombine(hashValue, p1[i]);
13107
13108     return hashValue;
13109 }
13110
13111 ExternalTypeBlobEntry::ExternalTypeBlobEntry(mdToken _assemblyRef, 
13112                                              mdToken _nestedClass,
13113                                              mdToken _nameSpace, 
13114                                              LPCSTR  _pName)
13115 {
13116    CONTRACTL
13117     {
13118         NOTHROW;
13119         GC_NOTRIGGER;
13120         PRECONDITION(CheckPointer(_pName));
13121     }
13122     CONTRACTL_END;
13123
13124     m_token  = idExternalTypeNil;
13125     m_assemblyRef = mdAssemblyRefNil; 
13126     m_nestedClass = idExternalTypeNil; 
13127     m_nameSpace   = idExternalNamespaceNil; 
13128     m_cbName = 0;
13129     m_pName  = NULL;
13130
13131     DWORD _cbName = (DWORD) strlen(_pName) + 1;
13132     LPSTR * pName = (LPSTR *) new (nothrow) CHAR[_cbName];
13133     if (pName != NULL)
13134     {
13135         m_assemblyRef = _assemblyRef;
13136         m_nestedClass = _nestedClass;
13137         m_nameSpace   = _nameSpace;
13138         m_cbName      = _cbName;
13139         memcpy(pName, _pName, _cbName);
13140         m_pName       = (LPCSTR) pName;
13141     }
13142 }
13143
13144 /* static */ const ExternalTypeBlobEntry *  ExternalTypeBlobEntry::FindOrAdd(PTR_Module pModule, 
13145                                                                              mdToken    _assemblyRef, 
13146                                                                              mdToken    _nestedClass,
13147                                                                              mdToken    _nameSpace, 
13148                                                                              LPCSTR     _pName)
13149 {
13150    CONTRACTL
13151     {
13152         NOTHROW;
13153         GC_NOTRIGGER;
13154     }
13155     CONTRACTL_END;
13156
13157     if ((_pName == NULL) || (::strlen(_pName) == 0))
13158         return NULL;
13159
13160     ExternalTypeBlobEntry sEntry(_assemblyRef, _nestedClass, _nameSpace, _pName);
13161
13162     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
13163     if (pEntry == NULL)
13164     {
13165         //
13166         // Not Found, add a new external type blob entry
13167         // 
13168         ExternalTypeBlobEntry *  newEntry = new (nothrow) ExternalTypeBlobEntry(_assemblyRef, _nestedClass, _nameSpace, _pName);
13169         if (newEntry == NULL)
13170             return NULL;
13171
13172         newEntry->newToken();                 // Assign a new ibc external type token
13173         CONTRACT_VIOLATION(ThrowsViolation);
13174         pModule->GetProfilingBlobTable()->Add(newEntry);
13175         pEntry = newEntry;
13176     }
13177
13178     //
13179     // Return the external type entry that we found or the new one that we just created
13180     // 
13181     _ASSERTE(pEntry->kind() == ExternalTypeDef);
13182     return static_cast<const ExternalTypeBlobEntry *>(pEntry);
13183 }
13184
13185 bool        ExternalSignatureBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
13186 {
13187     WRAPPER_NO_CONTRACT;
13188
13189     if (this->kind() != other->kind())
13190         return false;
13191
13192     const ExternalSignatureBlobEntry *  other2 = static_cast<const ExternalSignatureBlobEntry *>(other);
13193
13194     if (this->cbSig() != other2->cbSig())
13195         return false;
13196
13197     PCCOR_SIGNATURE  p1 = this->pSig();
13198     PCCOR_SIGNATURE  p2 = other2->pSig();
13199     
13200     for (DWORD i=0; (i < this->cbSig()); i++)
13201         if (p1[i] != p2[i])
13202             return false;
13203
13204     return true;
13205 }
13206
13207 size_t     ExternalSignatureBlobEntry::Hash() const
13208 {
13209     WRAPPER_NO_CONTRACT;
13210
13211     size_t hashValue = HashInit();
13212
13213     hashValue = HashCombine(hashValue, cbSig());
13214
13215     PCCOR_SIGNATURE  p1 = pSig();
13216     
13217     for (DWORD i=0; (i < cbSig()); i++)
13218         hashValue = HashCombine(hashValue, p1[i]);
13219
13220     return hashValue;
13221 }
13222
13223 ExternalSignatureBlobEntry::ExternalSignatureBlobEntry(DWORD _cbSig, PCCOR_SIGNATURE _pSig)
13224 {
13225     CONTRACTL
13226     {
13227         NOTHROW;
13228         GC_NOTRIGGER;
13229         PRECONDITION(_cbSig > 0);
13230         PRECONDITION(CheckPointer(_pSig));
13231     }
13232     CONTRACTL_END;
13233
13234     m_token  = idExternalSignatureNil;
13235     m_cbSig  = 0;
13236
13237     COR_SIGNATURE *  pNewSig = (COR_SIGNATURE *) new (nothrow) BYTE[_cbSig];
13238     if (pNewSig != NULL)
13239     {
13240         m_cbSig  = _cbSig;
13241         memcpy(pNewSig, _pSig, _cbSig);
13242     }
13243     m_pSig = const_cast<PCCOR_SIGNATURE>(pNewSig);
13244 }
13245
13246 /* static */ const ExternalSignatureBlobEntry *  ExternalSignatureBlobEntry::FindOrAdd(PTR_Module      pModule, 
13247                                                                                        DWORD           _cbSig, 
13248                                                                                        PCCOR_SIGNATURE _pSig)
13249 {
13250     CONTRACTL
13251     {
13252         NOTHROW;
13253         GC_NOTRIGGER;
13254     }
13255     CONTRACTL_END;
13256
13257     if ((_cbSig == 0) || (_pSig == NULL))
13258         return NULL;
13259
13260     ExternalSignatureBlobEntry sEntry(_cbSig, _pSig);
13261
13262     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
13263     if (pEntry == NULL)
13264     {
13265         //
13266         // Not Found, add a new external signature blob entry
13267         // 
13268         ExternalSignatureBlobEntry * newEntry = new (nothrow) ExternalSignatureBlobEntry(_cbSig, _pSig);
13269         if (newEntry == NULL)
13270             return NULL;
13271
13272         newEntry->newToken();                 // Assign a new ibc external signature token
13273         CONTRACT_VIOLATION(ThrowsViolation);
13274         pModule->GetProfilingBlobTable()->Add(newEntry);
13275         pEntry = newEntry;
13276     }
13277
13278     //
13279     // Return the external signature entry that we found or the new one that we just created
13280     // 
13281     _ASSERTE(pEntry->kind() == ExternalSignatureDef);
13282     return static_cast<const ExternalSignatureBlobEntry *>(pEntry);
13283 }
13284
13285 bool        ExternalMethodBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
13286 {
13287     WRAPPER_NO_CONTRACT;
13288
13289     if (this->kind() != other->kind())
13290         return false;
13291
13292     const ExternalMethodBlobEntry *  other2 = static_cast<const ExternalMethodBlobEntry *>(other);
13293
13294     if (this->nestedClass() != other2->nestedClass())
13295         return false;
13296
13297     if (this->signature() != other2->signature())
13298         return false;
13299
13300     if (this->cbName() != other2->cbName())
13301         return false;
13302
13303     LPCSTR p1 = this->pName();
13304     LPCSTR p2 = other2->pName();
13305     
13306     for (DWORD i=0; (i < this->cbName()); i++)
13307         if (p1[i] != p2[i])
13308             return false;
13309
13310     return true;
13311 }
13312
13313 size_t     ExternalMethodBlobEntry::Hash() const
13314 {
13315     WRAPPER_NO_CONTRACT;
13316
13317     size_t hashValue = HashInit();
13318
13319     hashValue = HashCombine(hashValue, nestedClass());
13320     hashValue = HashCombine(hashValue, signature());
13321
13322     LPCSTR p1 = pName();
13323     
13324     for (DWORD i=0; (i < cbName()); i++)
13325         hashValue = HashCombine(hashValue, p1[i]);
13326
13327     return hashValue;
13328 }
13329
13330 ExternalMethodBlobEntry::ExternalMethodBlobEntry(mdToken _nestedClass, 
13331                                                  mdToken _signature, 
13332                                                  LPCSTR  _pName)
13333 {
13334     CONTRACTL
13335     {
13336         NOTHROW;
13337         GC_NOTRIGGER;
13338         PRECONDITION(CheckPointer(_pName));
13339     }
13340     CONTRACTL_END;
13341
13342     m_token       = idExternalMethodNil;
13343     m_nestedClass = idExternalTypeNil; 
13344     m_signature   = idExternalSignatureNil; 
13345     m_cbName      = 0;
13346
13347     DWORD _cbName = (DWORD) strlen(_pName) + 1;
13348     LPSTR * pName = (LPSTR *) new (nothrow) CHAR[_cbName];
13349     if (pName != NULL)
13350         {
13351         m_nestedClass = _nestedClass;
13352         m_signature   = _signature;
13353         m_cbName      = _cbName;
13354         memcpy(pName, _pName, _cbName);
13355         m_pName       = (LPSTR) pName;
13356     }
13357         }
13358
13359 /* static */ const ExternalMethodBlobEntry *  ExternalMethodBlobEntry::FindOrAdd(
13360                                                              PTR_Module pModule, 
13361                                                              mdToken    _nestedClass, 
13362                                                              mdToken    _signature, 
13363                                                              LPCSTR     _pName)
13364 {
13365     CONTRACTL
13366         {
13367         NOTHROW;
13368         GC_NOTRIGGER;
13369         PRECONDITION(CheckPointer(_pName));
13370         }
13371     CONTRACTL_END;
13372
13373     if ((_pName == NULL) || (::strlen(_pName) == 0))
13374         return NULL;
13375
13376     ExternalMethodBlobEntry sEntry(_nestedClass, _signature, _pName);
13377
13378     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
13379     if (pEntry == NULL)
13380     {
13381         //
13382         // Not Found, add a new external type blob entry
13383         // 
13384         ExternalMethodBlobEntry *  newEntry;
13385         newEntry = new (nothrow) ExternalMethodBlobEntry(_nestedClass, _signature, _pName);
13386         if (newEntry == NULL)
13387             return NULL;
13388
13389         newEntry->newToken();                 // Assign a new ibc external method token
13390         CONTRACT_VIOLATION(ThrowsViolation);
13391         pModule->GetProfilingBlobTable()->Add(newEntry);
13392         pEntry = newEntry;
13393     }
13394
13395     //
13396     // Return the external method entry that we found or the new one that we just created
13397     // 
13398     _ASSERTE(pEntry->kind() == ExternalMethodDef);
13399     return static_cast<const ExternalMethodBlobEntry *>(pEntry);
13400 }
13401
13402
13403 static bool GetBasename(LPCWSTR _src, __out_ecount(dstlen) __out_z LPWSTR _dst, int dstlen)
13404 {
13405     LIMITED_METHOD_CONTRACT;
13406     LPCWSTR src = _src;
13407     LPWSTR  dst = _dst;
13408
13409     if ((src == NULL) || (dstlen <= 0))
13410         return false;
13411
13412     bool   inQuotes = false;
13413     LPWSTR dstLast = dst + (dstlen - 1);
13414     while (dst < dstLast)
13415     {
13416         WCHAR wch = *src++;
13417         if (wch == W('"'))
13418         {
13419             inQuotes = !inQuotes;
13420             continue;
13421         }
13422
13423         if (wch == 0)
13424             break;
13425
13426         *dst++ = wch;
13427
13428         if (!inQuotes)
13429         {
13430             if ((wch == W('\\')) || (wch == W(':')))
13431             {
13432                 dst = _dst;
13433             }
13434             else if (wch == W(' '))
13435             {
13436                 dst--;
13437                 break;
13438             }
13439         }
13440     }
13441     *dst++ = 0;
13442     return true;
13443 }
13444
13445 static void ProfileDataAllocateScenarioInfo(ProfileEmitter * pEmitter, LPCSTR scopeName, GUID* pMvid)
13446 {
13447     CONTRACTL
13448     {
13449         THROWS;
13450         GC_NOTRIGGER;
13451         MODE_ANY;
13452         INJECT_FAULT(COMPlusThrowOM());
13453     }
13454     CONTRACTL_END;
13455
13456     ProfileMap *profileMap = pEmitter->EmitNewSection(ScenarioInfo);
13457
13458     //
13459     // Allocate and initialize the scenario info section
13460     //
13461     {
13462         CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *siHeader;
13463         siHeader = (CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *) profileMap->Allocate(sizeof(CORBBTPROF_SCENARIO_INFO_SECTION_HEADER));
13464         
13465         siHeader->NumScenarios = 1;
13466         siHeader->TotalNumRuns = 1;
13467     }
13468
13469     //
13470     // Allocate and initialize the scenario header section
13471     //
13472     {
13473         LPCWSTR  pCmdLine    = GetCommandLineW();
13474         S_SIZE_T cCmdLine = S_SIZE_T(wcslen(pCmdLine));
13475         cCmdLine += 1;
13476         if (cCmdLine.IsOverflow())
13477         {
13478             ThrowHR(COR_E_OVERFLOW);
13479         }
13480         
13481         LPCWSTR  pSystemInfo = W("<machine,OS>");
13482         S_SIZE_T cSystemInfo = S_SIZE_T(wcslen(pSystemInfo));
13483         cSystemInfo += 1;
13484         if (cSystemInfo.IsOverflow())
13485         {
13486             ThrowHR(COR_E_OVERFLOW);
13487         }
13488         
13489         FILETIME runTime, unused1, unused2, unused3;
13490         GetProcessTimes(GetCurrentProcess(), &runTime, &unused1, &unused2, &unused3);
13491         
13492         WCHAR    scenarioName[256];
13493         GetBasename(pCmdLine, &scenarioName[0], 256);
13494         
13495         LPCWSTR  pName      = &scenarioName[0];
13496         S_SIZE_T cName      = S_SIZE_T(wcslen(pName));
13497         cName += 1;
13498         if (cName.IsOverflow())
13499         {
13500             ThrowHR(COR_E_OVERFLOW);
13501         }
13502
13503         S_SIZE_T sizeHeader = S_SIZE_T(sizeof(CORBBTPROF_SCENARIO_HEADER));
13504         sizeHeader += cName * S_SIZE_T(sizeof(WCHAR));
13505         if (sizeHeader.IsOverflow())
13506         {
13507             ThrowHR(COR_E_OVERFLOW);
13508         }
13509         
13510         S_SIZE_T sizeRun    = S_SIZE_T(sizeof(CORBBTPROF_SCENARIO_RUN));
13511         sizeRun += cCmdLine * S_SIZE_T(sizeof(WCHAR));
13512         sizeRun += cSystemInfo * S_SIZE_T(sizeof(WCHAR));
13513         if (sizeRun.IsOverflow())
13514         {
13515             ThrowHR(COR_E_OVERFLOW);
13516         }
13517         
13518         //
13519         // Allocate the Scenario Header struct
13520         // 
13521         SIZE_T sHeaderOffset;
13522         {
13523             CORBBTPROF_SCENARIO_HEADER *sHeader;
13524             S_SIZE_T sHeaderSize = sizeHeader + sizeRun;
13525             if (sHeaderSize.IsOverflow())
13526             {
13527                 ThrowHR(COR_E_OVERFLOW);
13528             }
13529             
13530             sHeaderOffset = profileMap->getCurrentOffset();
13531             sHeader = (CORBBTPROF_SCENARIO_HEADER *) profileMap->Allocate(sizeHeader.Value());
13532             
13533             sHeader->size              = sHeaderSize.Value();
13534             sHeader->scenario.ordinal  = 1;
13535             sHeader->scenario.mask     = 1;
13536             sHeader->scenario.priority = 0;
13537             sHeader->scenario.numRuns  = 1;
13538             sHeader->scenario.cName    = cName.Value();
13539             wcscpy_s(sHeader->scenario.name, cName.Value(), pName);
13540         }
13541
13542         //
13543         // Allocate the Scenario Run struct
13544         // 
13545         {
13546             CORBBTPROF_SCENARIO_RUN *sRun;
13547             sRun = (CORBBTPROF_SCENARIO_RUN *)  profileMap->Allocate(sizeRun.Value());
13548             
13549             sRun->runTime     = runTime;
13550             sRun->mvid        = *pMvid;
13551             sRun->cCmdLine    = cCmdLine.Value();
13552             sRun->cSystemInfo = cSystemInfo.Value();
13553             wcscpy_s(sRun->cmdLine, cCmdLine.Value(), pCmdLine);
13554             wcscpy_s(sRun->cmdLine+cCmdLine.Value(), cSystemInfo.Value(), pSystemInfo);
13555         }
13556 #ifdef _DEBUG
13557         {
13558             CORBBTPROF_SCENARIO_HEADER * sHeader;
13559             sHeader = (CORBBTPROF_SCENARIO_HEADER *) profileMap->getOffsetPtr(sHeaderOffset);
13560             assert(sHeader->size == sHeader->Size());
13561         }
13562 #endif
13563     }
13564 }
13565
13566 static void ProfileDataAllocateMethodBlockCounts(ProfileEmitter * pEmitter, CORCOMPILE_METHOD_PROFILE_LIST * pMethodProfileListHead)
13567 {
13568     CONTRACTL
13569     {
13570         THROWS;
13571         GC_NOTRIGGER;
13572         MODE_ANY;
13573         INJECT_FAULT(COMPlusThrowOM());
13574     }
13575     CONTRACTL_END;
13576
13577     ProfileMap *profileMap = pEmitter->EmitNewSection(MethodBlockCounts);
13578     
13579     //
13580     // Allocate and initialize the method block count section
13581     //
13582     SIZE_T mbcHeaderOffset;
13583     {
13584         CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *mbcHeader;
13585         mbcHeaderOffset = profileMap->getCurrentOffset();
13586         mbcHeader = (CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *)
13587             profileMap->Allocate(sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER));
13588         mbcHeader->NumMethods = 0;  // This gets filled in later
13589     }
13590
13591     ULONG numMethods = 0;   // We count the number of methods that were executed
13592
13593     for (CORCOMPILE_METHOD_PROFILE_LIST * methodProfileList = pMethodProfileListHead;
13594          methodProfileList;
13595          methodProfileList = methodProfileList->next)
13596     {
13597         CORBBTPROF_METHOD_HEADER * pInfo = methodProfileList->GetInfo();
13598         
13599         assert(pInfo->size == pInfo->Size());
13600         
13601         //
13602         // We set methodWasExecuted based upon the ExecutionCount of the very first block
13603         // 
13604         bool methodWasExecuted = (pInfo->method.block[0].ExecutionCount > 0);
13605         
13606         //
13607         // If the method was not executed then we don't need to output this methods block counts
13608         //
13609         SIZE_T methodHeaderOffset;
13610         if (methodWasExecuted)
13611         {
13612             DWORD profileDataSize = pInfo->size;
13613             methodHeaderOffset = profileMap->getCurrentOffset();
13614             CORBBTPROF_METHOD_HEADER *methodHeader = (CORBBTPROF_METHOD_HEADER *) profileMap->Allocate(profileDataSize);
13615             memcpy(methodHeader, pInfo, profileDataSize);
13616             numMethods++;
13617         }
13618         
13619         // Reset all of the basic block counts to zero
13620         for (ULONG i=0; (i <  pInfo->method.cBlock); i++ )
13621         {
13622             //
13623             // If methodWasExecuted is false then every block's ExecutionCount should also be zero
13624             //
13625             _ASSERTE(methodWasExecuted  || (pInfo->method.block[i].ExecutionCount == 0));
13626             
13627             pInfo->method.block[i].ExecutionCount = 0;
13628         }
13629     }
13630     
13631     {
13632         CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *mbcHeader;
13633         // We have to refetch the mbcHeader as calls to Allocate will resize and thus move the mbcHeader
13634         mbcHeader = (CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *) profileMap->getOffsetPtr(mbcHeaderOffset);
13635         mbcHeader->NumMethods = numMethods;
13636     }
13637 }
13638
13639 /*static*/ void Module::ProfileDataAllocateTokenLists(ProfileEmitter * pEmitter, Module::TokenProfileData* pTokenProfileData)
13640 {
13641     CONTRACTL
13642     {
13643         THROWS;
13644         GC_NOTRIGGER;
13645         MODE_ANY;
13646         INJECT_FAULT(COMPlusThrowOM());
13647     }
13648     CONTRACTL_END;
13649
13650     //
13651     // Allocate and initialize the token list sections
13652     //
13653     if (pTokenProfileData)
13654     {
13655         for (int format = 0; format < (int)SectionFormatCount; format++)
13656         {
13657             CQuickArray<CORBBTPROF_TOKEN_INFO> *pTokenArray = &(pTokenProfileData->m_formats[format].tokenArray);
13658             
13659             if (pTokenArray->Size() != 0)
13660             {
13661                 ProfileMap *  profileMap = pEmitter->EmitNewSection((SectionFormat) format);
13662                 
13663                 CORBBTPROF_TOKEN_LIST_SECTION_HEADER *header;
13664                 header = (CORBBTPROF_TOKEN_LIST_SECTION_HEADER *)
13665                     profileMap->Allocate(sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER) +
13666                                          pTokenArray->Size() * sizeof(CORBBTPROF_TOKEN_INFO));
13667                 
13668                 header->NumTokens = pTokenArray->Size();
13669                 memcpy( (header + 1), &((*pTokenArray)[0]), pTokenArray->Size() * sizeof(CORBBTPROF_TOKEN_INFO));
13670                 
13671                 // Reset the collected tokens
13672                 for (unsigned i = 0; i < CORBBTPROF_TOKEN_MAX_NUM_FLAGS; i++)
13673                 {
13674                     pTokenProfileData->m_formats[format].tokenBitmaps[i].Reset();
13675                 }
13676                 pTokenProfileData->m_formats[format].tokenArray.ReSizeNoThrow(0);
13677             }
13678         }
13679     }
13680 }
13681
13682 static void ProfileDataAllocateTokenDefinitions(ProfileEmitter * pEmitter, Module * pModule)
13683 {
13684     CONTRACTL
13685     {
13686         THROWS;
13687         GC_NOTRIGGER;
13688         MODE_ANY;
13689         INJECT_FAULT(COMPlusThrowOM());
13690     }
13691     CONTRACTL_END;
13692
13693     //
13694     // Allocate and initialize the ibc token definition section (aka the Blob stream)
13695     //
13696     ProfileMap *  profileMap = pEmitter->EmitNewSection(BlobStream);
13697
13698     // Compute the size of the metadata section:
13699     // It is the sum of all of the Metadata Profile pool entries
13700     //  plus the sum of all of the Param signature entries
13701     //
13702     size_t totalSize = 0;
13703
13704     for (ProfilingBlobTable::Iterator cur = pModule->GetProfilingBlobTable()->Begin(),
13705                                       end = pModule->GetProfilingBlobTable()->End(); 
13706          (cur != end); 
13707          cur++)
13708     {
13709         const ProfilingBlobEntry * pEntry = *cur;
13710         size_t blobElementSize = pEntry->varSize();
13711         switch (pEntry->kind()) {
13712         case ParamTypeSpec:
13713         case ParamMethodSpec:
13714             blobElementSize += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY);
13715             break;
13716
13717         case ExternalNamespaceDef:
13718             blobElementSize += sizeof(CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY);
13719             break;
13720
13721         case ExternalTypeDef:
13722             blobElementSize += sizeof(CORBBTPROF_BLOB_TYPE_DEF_ENTRY);
13723             break;
13724
13725         case ExternalSignatureDef:
13726             blobElementSize += sizeof(CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY);
13727             break;
13728
13729         case ExternalMethodDef:
13730             blobElementSize += sizeof(CORBBTPROF_BLOB_METHOD_DEF_ENTRY);
13731             break;
13732
13733         default:
13734             _ASSERTE(!"Unexpected blob type");
13735             break;
13736         }
13737         totalSize += blobElementSize;
13738     }
13739
13740     profileMap->Allocate(totalSize);
13741
13742     size_t currentPos = 0;
13743
13744     // Traverse each element and record it
13745     size_t blobElementSize = 0;
13746     for (ProfilingBlobTable::Iterator cur = pModule->GetProfilingBlobTable()->Begin(),
13747                                       end = pModule->GetProfilingBlobTable()->End(); 
13748          (cur != end); 
13749          cur++, currentPos += blobElementSize)
13750     {
13751         const ProfilingBlobEntry * pEntry = *cur;
13752         blobElementSize = pEntry->varSize();
13753         void *profileData = profileMap->getOffsetPtr(currentPos);
13754
13755         switch (pEntry->kind()) {
13756         case ParamTypeSpec:
13757         {
13758             CORBBTPROF_BLOB_PARAM_SIG_ENTRY *  bProfileData      = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY*) profileData;
13759             const TypeSpecBlobEntry *          typeSpecBlobEntry = static_cast<const TypeSpecBlobEntry *>(pEntry);
13760
13761             blobElementSize         += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY);
13762             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
13763             bProfileData->blob.type  = typeSpecBlobEntry->kind();
13764             bProfileData->blob.token = typeSpecBlobEntry->token();
13765             _ASSERTE(typeSpecBlobEntry->cbSig() > 0);
13766             bProfileData->cSig       = typeSpecBlobEntry->cbSig();
13767             memcpy(&bProfileData->sig[0], typeSpecBlobEntry->pSig(), typeSpecBlobEntry->cbSig());
13768             break;
13769         }
13770
13771         case ParamMethodSpec:
13772         {
13773             CORBBTPROF_BLOB_PARAM_SIG_ENTRY *  bProfileData        = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY*) profileData;
13774             const MethodSpecBlobEntry *        methodSpecBlobEntry = static_cast<const MethodSpecBlobEntry *>(pEntry);
13775
13776             blobElementSize         += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY);
13777             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
13778             bProfileData->blob.type  = methodSpecBlobEntry->kind();
13779             bProfileData->blob.token = methodSpecBlobEntry->token();
13780             _ASSERTE(methodSpecBlobEntry->cbSig() > 0);
13781             bProfileData->cSig       = methodSpecBlobEntry->cbSig();
13782             memcpy(&bProfileData->sig[0], methodSpecBlobEntry->pSig(), methodSpecBlobEntry->cbSig());
13783             break;
13784         }
13785
13786         case ExternalNamespaceDef:
13787         {
13788             CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY *  bProfileData        = (CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY*) profileData;
13789             const ExternalNamespaceBlobEntry *     namespaceBlobEntry  = static_cast<const ExternalNamespaceBlobEntry *>(pEntry);
13790
13791             blobElementSize         += sizeof(CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY);
13792             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
13793             bProfileData->blob.type  = namespaceBlobEntry->kind();
13794             bProfileData->blob.token = namespaceBlobEntry->token();
13795             _ASSERTE(namespaceBlobEntry->cbName() > 0);
13796             bProfileData->cName      = namespaceBlobEntry->cbName();
13797             memcpy(&bProfileData->name[0], namespaceBlobEntry->pName(), namespaceBlobEntry->cbName());
13798             break;
13799         }
13800             
13801         case ExternalTypeDef:
13802         {
13803             CORBBTPROF_BLOB_TYPE_DEF_ENTRY *       bProfileData        = (CORBBTPROF_BLOB_TYPE_DEF_ENTRY*) profileData;
13804             const ExternalTypeBlobEntry *          typeBlobEntry       = static_cast<const ExternalTypeBlobEntry *>(pEntry);
13805
13806             blobElementSize         += sizeof(CORBBTPROF_BLOB_TYPE_DEF_ENTRY);
13807             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
13808             bProfileData->blob.type  = typeBlobEntry->kind();
13809             bProfileData->blob.token = typeBlobEntry->token();
13810             bProfileData->assemblyRefToken = typeBlobEntry->assemblyRef();
13811             bProfileData->nestedClassToken = typeBlobEntry->nestedClass();
13812             bProfileData->nameSpaceToken   = typeBlobEntry->nameSpace();
13813             _ASSERTE(typeBlobEntry->cbName() > 0);
13814             bProfileData->cName            = typeBlobEntry->cbName();
13815             memcpy(&bProfileData->name[0], typeBlobEntry->pName(), typeBlobEntry->cbName());
13816             break;
13817         }
13818             
13819         case ExternalSignatureDef:
13820         {
13821             CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY *  bProfileData        = (CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY*) profileData;
13822             const ExternalSignatureBlobEntry *     signatureBlobEntry  = static_cast<const ExternalSignatureBlobEntry *>(pEntry);
13823
13824             blobElementSize         += sizeof(CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY);
13825             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
13826             bProfileData->blob.type  = signatureBlobEntry->kind();
13827             bProfileData->blob.token = signatureBlobEntry->token();
13828             _ASSERTE(signatureBlobEntry->cbSig() > 0);
13829             bProfileData->cSig       = signatureBlobEntry->cbSig();
13830             memcpy(&bProfileData->sig[0], signatureBlobEntry->pSig(), signatureBlobEntry->cbSig());
13831             break;
13832         }
13833
13834         case ExternalMethodDef:
13835         {
13836             CORBBTPROF_BLOB_METHOD_DEF_ENTRY *     bProfileData        = (CORBBTPROF_BLOB_METHOD_DEF_ENTRY*) profileData;
13837             const ExternalMethodBlobEntry *        methodBlobEntry     = static_cast<const ExternalMethodBlobEntry *>(pEntry);
13838
13839             blobElementSize         += sizeof(CORBBTPROF_BLOB_METHOD_DEF_ENTRY);
13840             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
13841             bProfileData->blob.type  = methodBlobEntry->kind();
13842             bProfileData->blob.token = methodBlobEntry->token();
13843             bProfileData->nestedClassToken = methodBlobEntry->nestedClass();
13844             bProfileData->signatureToken   = methodBlobEntry->signature();
13845             _ASSERTE(methodBlobEntry->cbName() > 0);
13846             bProfileData->cName            = methodBlobEntry->cbName();
13847             memcpy(&bProfileData->name[0], methodBlobEntry->pName(), methodBlobEntry->cbName());
13848             break;
13849         }
13850
13851         default:
13852             _ASSERTE(!"Unexpected blob type");
13853             break;
13854         }
13855     }
13856     
13857     _ASSERTE(currentPos == totalSize);
13858     
13859     // Emit a terminating entry with type EndOfBlobStream to mark the end
13860     DWORD mdElementSize = sizeof(CORBBTPROF_BLOB_ENTRY);
13861     void *profileData = profileMap->Allocate(mdElementSize);
13862     memset(profileData, 0, mdElementSize);
13863     
13864     CORBBTPROF_BLOB_ENTRY* mdProfileData = (CORBBTPROF_BLOB_ENTRY*) profileData;
13865     mdProfileData->type = EndOfBlobStream;
13866     mdProfileData->size = sizeof(CORBBTPROF_BLOB_ENTRY);
13867 }
13868
13869 // Responsible for writing out the profile data if the COMPlus_BBInstr 
13870 // environment variable is set.  This is called when the module is unloaded
13871 // (usually at shutdown).
13872 HRESULT Module::WriteMethodProfileDataLogFile(bool cleanup)
13873 {
13874     CONTRACTL
13875     {
13876         INSTANCE_CHECK;
13877         NOTHROW;
13878         GC_TRIGGERS;
13879         MODE_ANY;
13880         INJECT_FAULT(return E_OUTOFMEMORY;);
13881     }
13882     CONTRACTL_END;
13883
13884     HRESULT hr = S_OK;
13885
13886     if (IsResource())
13887         return S_OK;
13888
13889     EX_TRY
13890     {
13891         if (GetAssembly()->IsInstrumented() && (m_pProfilingBlobTable != NULL) && (m_tokenProfileData != NULL))
13892         {
13893             ProfileEmitter * pEmitter = new ProfileEmitter();
13894
13895             // Get this ahead of time - metadata access may be logged, which will
13896             // take the m_tokenProfileData->crst, which we take a couple lines below
13897             LPCSTR pszName;
13898             GUID mvid;
13899             IfFailThrow(GetMDImport()->GetScopeProps(&pszName, &mvid));
13900             
13901             CrstHolder ch(&m_tokenProfileData->crst);
13902             
13903             //
13904             // Create the scenario info section
13905             //
13906             ProfileDataAllocateScenarioInfo(pEmitter, pszName, &mvid);
13907
13908             //
13909             // Create the method block count section
13910             // 
13911             ProfileDataAllocateMethodBlockCounts(pEmitter, m_methodProfileList);
13912
13913             //
13914             // Create the token list sections
13915             // 
13916             ProfileDataAllocateTokenLists(pEmitter, m_tokenProfileData);
13917
13918             //
13919             // Create the ibc token definition section (aka the Blob stream)
13920             // 
13921             ProfileDataAllocateTokenDefinitions(pEmitter, this);
13922   
13923             //
13924             // Now store the profile data in the ibc file
13925             //
13926             ProfileMap profileImage;
13927             pEmitter->Serialize(&profileImage, mvid);
13928
13929             HandleHolder profileDataFile(OpenMethodProfileDataLogFile(mvid));
13930
13931             ULONG count;
13932             BOOL result = WriteFile(profileDataFile, profileImage.getOffsetPtr(0), profileImage.getCurrentOffset(), &count, NULL);
13933             if (!result || (count != profileImage.getCurrentOffset()))
13934             {
13935                 DWORD lasterror = GetLastError();
13936                 _ASSERTE(!"Error writing ibc profile data to file");
13937                 hr = HRESULT_FROM_WIN32(lasterror);
13938             }
13939         }
13940
13941         if (cleanup)
13942         {
13943             DeleteProfilingData();
13944         }
13945     }
13946     EX_CATCH
13947     {
13948         hr = E_FAIL;
13949     }
13950     EX_END_CATCH(SwallowAllExceptions)
13951
13952     return hr;
13953 }
13954
13955
13956 /* static */
13957 void Module::WriteAllModuleProfileData(bool cleanup)
13958 {
13959     CONTRACTL
13960     {
13961         NOTHROW;
13962         GC_TRIGGERS;
13963         MODE_ANY;
13964     }
13965     CONTRACTL_END;
13966
13967     // Iterate over all the app domains; for each one iterator over its
13968     // assemblies; for each one iterate over its modules.
13969     EX_TRY
13970     {
13971         AppDomainIterator appDomainIterator(FALSE);
13972         while(appDomainIterator.Next())
13973         {
13974             AppDomain * appDomain = appDomainIterator.GetDomain();
13975             AppDomain::AssemblyIterator assemblyIterator = appDomain->IterateAssembliesEx(
13976                 (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution));
13977             CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
13978
13979             while (assemblyIterator.Next(pDomainAssembly.This()))
13980             {
13981                 DomainModuleIterator i = pDomainAssembly->IterateModules(kModIterIncludeLoaded);
13982                 while (i.Next())
13983                 {
13984                     /*hr=*/i.GetModule()->WriteMethodProfileDataLogFile(cleanup);
13985                 }
13986             }
13987         }
13988     }
13989     EX_CATCH
13990     { }
13991     EX_END_CATCH(SwallowAllExceptions);
13992 }
13993
13994 PTR_ProfilingBlobTable Module::GetProfilingBlobTable()
13995 {
13996     LIMITED_METHOD_CONTRACT;
13997     return m_pProfilingBlobTable;
13998 }
13999
14000 void Module::CreateProfilingData()
14001 {
14002     TokenProfileData *tpd = TokenProfileData::CreateNoThrow();
14003     
14004     PVOID pv = InterlockedCompareExchangeT(&m_tokenProfileData, tpd, NULL);
14005     if (pv != NULL)
14006     {
14007         delete tpd;
14008     }
14009     
14010     PTR_ProfilingBlobTable ppbt = new (nothrow) ProfilingBlobTable();
14011
14012     if (ppbt != NULL)
14013     {
14014         pv = InterlockedCompareExchangeT(&m_pProfilingBlobTable, ppbt, NULL);
14015         if (pv != NULL)
14016         {
14017             delete ppbt;
14018         }
14019     }
14020 }
14021
14022 void Module::DeleteProfilingData()
14023 {
14024     if (m_pProfilingBlobTable != NULL)
14025     {
14026         for (ProfilingBlobTable::Iterator cur = m_pProfilingBlobTable->Begin(),
14027                                           end = m_pProfilingBlobTable->End(); 
14028              (cur != end); 
14029              cur++)
14030         {
14031             const ProfilingBlobEntry *  pCurrentEntry = *cur;
14032             delete pCurrentEntry;
14033         }
14034         delete m_pProfilingBlobTable;
14035         m_pProfilingBlobTable = NULL;
14036     }
14037
14038     if (m_tokenProfileData != NULL)
14039     {
14040         delete m_tokenProfileData;
14041         m_tokenProfileData = NULL;
14042     }
14043     
14044     // the metadataProfileData is free'ed in destructor of the corresponding MetaDataTracker
14045 }
14046 #endif //FEATURE_PREJIT
14047
14048 #ifdef FEATURE_MIXEDMODE
14049 void Module::SetIsIJWFixedUp()
14050 {
14051     LIMITED_METHOD_CONTRACT;
14052     FastInterlockOr(&m_dwTransientFlags, IS_IJW_FIXED_UP);
14053 }
14054 #endif
14055
14056
14057 #ifdef FEATURE_PREJIT
14058 /* static */
14059 Module::TokenProfileData *Module::TokenProfileData::CreateNoThrow(void)
14060 {
14061     STATIC_CONTRACT_NOTHROW;
14062
14063     TokenProfileData *tpd = NULL;
14064
14065     EX_TRY
14066     {
14067         //
14068         // This constructor calls crst.Init(), which may throw.  So putting (nothrow) doesn't
14069         // do what we would want it to.  Thus I wrap it here in a TRY/CATCH and revert to NULL
14070         // if it fails.
14071         //
14072         tpd = new TokenProfileData();
14073     }
14074     EX_CATCH
14075     {
14076         tpd = NULL;
14077     }
14078     EX_END_CATCH(SwallowAllExceptions);
14079
14080     return tpd;
14081 }
14082
14083 #endif // FEATURE_PREJIT
14084
14085 #endif // !DACCESS_COMPILE
14086
14087 #ifndef DACCESS_COMPILE
14088 void Module::SetBeingUnloaded()
14089 {
14090     LIMITED_METHOD_CONTRACT;
14091     FastInterlockOr((ULONG*)&m_dwTransientFlags, IS_BEING_UNLOADED);
14092 }
14093 #endif
14094
14095 #ifdef FEATURE_PREJIT 
14096 void Module::LogTokenAccess(mdToken token, SectionFormat format, ULONG flagnum)
14097 {
14098     CONTRACTL
14099     {
14100         INSTANCE_CHECK;
14101         NOTHROW;
14102         GC_NOTRIGGER;
14103         MODE_ANY;
14104         PRECONDITION(g_IBCLogger.InstrEnabled());
14105         PRECONDITION(flagnum < CORBBTPROF_TOKEN_MAX_NUM_FLAGS);
14106     }
14107     CONTRACTL_END;
14108
14109 #ifndef DACCESS_COMPILE 
14110
14111     //
14112     // If we are in ngen instrumentation mode, then we should record this token.
14113     //
14114
14115     if (!m_nativeImageProfiling)
14116         return;
14117
14118     mdToken rid = RidFromToken(token);
14119     CorTokenType  tkType  = (CorTokenType) TypeFromToken(token);
14120     SectionFormat tkKind  = (SectionFormat) (tkType >> 24);
14121
14122     if ((rid == 0) && (tkKind < (SectionFormat) TBL_COUNT))
14123         return;
14124
14125     FAULT_NOT_FATAL();
14126
14127     _ASSERTE(TypeProfilingData   == FirstTokenFlagSection + TBL_TypeDef);
14128     _ASSERTE(MethodProfilingData == FirstTokenFlagSection + TBL_Method);
14129     _ASSERTE(SectionFormatCount  >= FirstTokenFlagSection + TBL_COUNT + 4);
14130
14131     if (!m_tokenProfileData)
14132     {
14133         CreateProfilingData();
14134     }
14135
14136     if (!m_tokenProfileData)
14137     {
14138         return;
14139     }
14140
14141     if (tkKind == (SectionFormat) (ibcTypeSpec >> 24))
14142         tkKind = IbcTypeSpecSection;
14143     else if (tkKind == (SectionFormat) (ibcMethodSpec >> 24))
14144         tkKind = IbcMethodSpecSection;
14145
14146     _ASSERTE(tkKind < SectionFormatCount);
14147     if (tkKind >= SectionFormatCount)
14148     {
14149         return;
14150     }
14151     
14152     CQuickArray<CORBBTPROF_TOKEN_INFO> * pTokenArray  = &m_tokenProfileData->m_formats[format].tokenArray;
14153     RidBitmap *                          pTokenBitmap = &m_tokenProfileData->m_formats[tkKind].tokenBitmaps[flagnum];
14154
14155     // Have we seen this token with this flag already?
14156     if (pTokenBitmap->IsTokenInBitmap(token))
14157     {
14158         return;
14159     }
14160
14161     // Insert the token to the bitmap
14162     if (FAILED(pTokenBitmap->InsertToken(token)))
14163     {
14164         return;
14165     }
14166
14167     ULONG flag = 1 << flagnum;
14168
14169     // [ToDo] Fix: this is a sequential search and can be very slow
14170     for (unsigned int i = 0; i < pTokenArray->Size(); i++)
14171     {
14172         if ((*pTokenArray)[i].token == token)
14173         {
14174             _ASSERTE(! ((*pTokenArray)[i].flags & flag));
14175             (*pTokenArray)[i].flags |= flag;
14176             return;
14177         }
14178     }
14179
14180     if (FAILED(pTokenArray->ReSizeNoThrow(pTokenArray->Size() + 1)))
14181     {
14182         return;
14183     }
14184
14185     (*pTokenArray)[pTokenArray->Size() - 1].token = token;
14186     (*pTokenArray)[pTokenArray->Size() - 1].flags = flag;
14187     (*pTokenArray)[pTokenArray->Size() - 1].scenarios = 0;
14188
14189 #endif // !DACCESS_COMPILE
14190 }
14191
14192 void Module::LogTokenAccess(mdToken token, ULONG flagNum)
14193 {
14194     WRAPPER_NO_CONTRACT;
14195     SectionFormat format = (SectionFormat)((TypeFromToken(token)>>24) + FirstTokenFlagSection);
14196     if (FirstTokenFlagSection <= format && format < SectionFormatCount)
14197     {
14198         LogTokenAccess(token, format, flagNum);
14199     }
14200 }
14201 #endif // FEATURE_PREJIT
14202
14203 #ifndef DACCESS_COMPILE
14204 #ifdef FEATURE_PREJIT
14205
14206 //
14207 // Encoding callbacks
14208 //
14209
14210 /*static*/ DWORD Module::EncodeModuleHelper(void * pModuleContext, Module *pReferencedModule)
14211 {
14212     Module* pReferencingModule = (Module *) pModuleContext;
14213     _ASSERTE(pReferencingModule != pReferencedModule);
14214
14215     Assembly *pReferencingAssembly = pReferencingModule->GetAssembly();
14216     Assembly *pReferencedAssembly  = pReferencedModule->GetAssembly();
14217
14218     _ASSERTE(pReferencingAssembly != pReferencedAssembly);
14219
14220     if (pReferencedAssembly == pReferencingAssembly)
14221     {
14222         return 0;
14223     }
14224
14225     mdAssemblyRef token = pReferencingModule->FindAssemblyRef(pReferencedAssembly);
14226
14227     if (IsNilToken(token))
14228     {
14229         return ENCODE_MODULE_FAILED;
14230     }
14231
14232     return RidFromToken(token);
14233 }
14234
14235 /*static*/ void Module::TokenDefinitionHelper(void* pModuleContext, Module *pReferencedModule, DWORD index, mdToken* pToken)
14236 {
14237     LIMITED_METHOD_CONTRACT;
14238     HRESULT              hr;
14239     Module *             pReferencingModule = (Module *) pModuleContext;
14240     mdAssemblyRef        mdAssemblyRef      = TokenFromRid(index, mdtAssemblyRef);
14241     IMDInternalImport *  pImport            = pReferencedModule->GetMDImport();
14242     LPCUTF8              szName             = NULL;
14243     
14244     if (TypeFromToken(*pToken) == mdtTypeDef)
14245     {
14246         //
14247         // Compute nested type (if any)
14248         // 
14249         mdTypeDef mdEnclosingType = idExternalTypeNil;
14250         hr = pImport->GetNestedClassProps(*pToken, &mdEnclosingType);
14251         // If there's not enclosing type, then hr=CLDB_E_RECORD_NOTFOUND and mdEnclosingType is unchanged
14252         _ASSERTE((hr == S_OK) || (hr == CLDB_E_RECORD_NOTFOUND));
14253         
14254         if (!IsNilToken(mdEnclosingType))
14255         {
14256             _ASSERT(TypeFromToken(mdEnclosingType) ==  mdtTypeDef);
14257             TokenDefinitionHelper(pModuleContext, pReferencedModule, index, &mdEnclosingType);
14258         }
14259         _ASSERT(TypeFromToken(mdEnclosingType) == ibcExternalType);
14260         
14261         //
14262         // Compute type name and namespace.
14263         //
14264         LPCUTF8 szNamespace = NULL;
14265         hr = pImport->GetNameOfTypeDef(*pToken, &szName, &szNamespace);
14266         _ASSERTE(hr == S_OK);
14267         
14268         //
14269         // Transform namespace string into ibc external namespace token
14270         // 
14271         idExternalNamespace idNamespace = idExternalNamespaceNil;
14272         if (szNamespace != NULL)
14273         {
14274             const ExternalNamespaceBlobEntry *  pNamespaceEntry;
14275             pNamespaceEntry = ExternalNamespaceBlobEntry::FindOrAdd(pReferencingModule, szNamespace);
14276             if (pNamespaceEntry != NULL)
14277             {
14278                 idNamespace = pNamespaceEntry->token();
14279             }
14280         }
14281         _ASSERTE(TypeFromToken(idNamespace) == ibcExternalNamespace);
14282
14283         //
14284         // Transform type name into ibc external type token
14285         // 
14286         idExternalType idType = idExternalTypeNil;
14287         _ASSERTE(szName != NULL);
14288         const ExternalTypeBlobEntry *  pTypeEntry = NULL;
14289         pTypeEntry = ExternalTypeBlobEntry::FindOrAdd(pReferencingModule, 
14290                                                       mdAssemblyRef, 
14291                                                       mdEnclosingType,
14292                                                       idNamespace, 
14293                                                       szName);
14294         if (pTypeEntry != NULL)
14295         {
14296             idType = pTypeEntry->token();
14297         }
14298         _ASSERTE(TypeFromToken(idType) == ibcExternalType);
14299
14300         *pToken = idType;   // Remap pToken to our idExternalType token 
14301     }
14302     else if (TypeFromToken(*pToken) == mdtMethodDef)
14303     {
14304         //
14305         // Compute nested type (if any)
14306         // 
14307         mdTypeDef mdEnclosingType = idExternalTypeNil;
14308         hr = pImport->GetParentToken(*pToken, &mdEnclosingType);
14309         _ASSERTE(!FAILED(hr));
14310
14311         if (!IsNilToken(mdEnclosingType))
14312         {
14313             _ASSERT(TypeFromToken(mdEnclosingType) ==  mdtTypeDef);
14314             TokenDefinitionHelper(pModuleContext, pReferencedModule, index, &mdEnclosingType);
14315         }
14316         _ASSERT(TypeFromToken(mdEnclosingType) == ibcExternalType);
14317
14318         //
14319         // Compute the method name and signature
14320         // 
14321         PCCOR_SIGNATURE pSig = NULL;
14322         DWORD           cbSig = 0;
14323         hr = pImport->GetNameAndSigOfMethodDef(*pToken, &pSig, &cbSig, &szName);
14324         _ASSERTE(hr == S_OK);
14325         
14326         //
14327         // Transform signature into ibc external signature token
14328         // 
14329         idExternalSignature idSignature = idExternalSignatureNil;
14330         if (pSig != NULL)
14331         {
14332             const ExternalSignatureBlobEntry *  pSignatureEntry;
14333             pSignatureEntry = ExternalSignatureBlobEntry::FindOrAdd(pReferencingModule, cbSig, pSig);
14334             if (pSignatureEntry != NULL)
14335             {
14336                 idSignature = pSignatureEntry->token();
14337             }
14338         }
14339         _ASSERTE(TypeFromToken(idSignature) == ibcExternalSignature);
14340
14341         //
14342         // Transform method name into ibc external method token
14343         // 
14344         idExternalMethod idMethod = idExternalMethodNil;
14345         _ASSERTE(szName != NULL);
14346         const ExternalMethodBlobEntry *  pMethodEntry = NULL;
14347         pMethodEntry = ExternalMethodBlobEntry::FindOrAdd(pReferencingModule, 
14348                                                           mdEnclosingType,
14349                                                           idSignature, 
14350                                                           szName);
14351         if (pMethodEntry != NULL)
14352         {
14353             idMethod = pMethodEntry->token();
14354         }
14355         _ASSERTE(TypeFromToken(idMethod) == ibcExternalMethod);
14356
14357         *pToken = idMethod;   // Remap pToken to our idMethodSpec token 
14358     }
14359     else
14360     {
14361         _ASSERTE(!"Unexpected token type");
14362     }
14363 }
14364
14365 idTypeSpec Module::LogInstantiatedType(TypeHandle typeHnd, ULONG flagNum)
14366 {
14367     CONTRACT(idTypeSpec)
14368     {
14369         NOTHROW;
14370         GC_NOTRIGGER;
14371         MODE_ANY;
14372         PRECONDITION(g_IBCLogger.InstrEnabled());
14373         PRECONDITION(!typeHnd.HasUnrestoredTypeKey());
14374         // We want to report the type only in its own loader module as a type's
14375         // MethodTable can only live in its own loader module.
14376         // We can relax this if we allow a (duplicate) MethodTable to live
14377         // in any module (which might be needed for ngen of generics)
14378 #ifdef FEATURE_PREJIT
14379         PRECONDITION(this == GetPreferredZapModuleForTypeHandle(typeHnd));
14380 #endif
14381     }
14382     CONTRACT_END;
14383
14384     idTypeSpec result = idTypeSpecNil;
14385
14386     if (m_nativeImageProfiling)
14387     {
14388         CONTRACT_VIOLATION(ThrowsViolation|FaultViolation|GCViolation);
14389
14390         SigBuilder sigBuilder;
14391
14392         ZapSig zapSig(this, this, ZapSig::IbcTokens, 
14393                         Module::EncodeModuleHelper, Module::TokenDefinitionHelper);
14394         BOOL fSuccess = zapSig.GetSignatureForTypeHandle(typeHnd, &sigBuilder);
14395
14396         // a return value of 0 indicates a failure to create the signature
14397         if (fSuccess)
14398         {
14399             DWORD cbSig;
14400             PCCOR_SIGNATURE pSig = (PCCOR_SIGNATURE)sigBuilder.GetSignature(&cbSig);
14401
14402             ULONG flag = (1 << flagNum);
14403             TypeSpecBlobEntry *  pEntry = const_cast<TypeSpecBlobEntry *>(TypeSpecBlobEntry::FindOrAdd(this, cbSig, pSig));
14404             if (pEntry != NULL)
14405             {
14406                 // Update the flags with any new bits
14407                 pEntry->orFlag(flag);
14408                 result = pEntry->token();
14409             }
14410         }
14411     }
14412     _ASSERTE(TypeFromToken(result) == ibcTypeSpec);
14413
14414     RETURN result;
14415 }
14416
14417 idMethodSpec Module::LogInstantiatedMethod(const MethodDesc * md, ULONG flagNum)
14418 {
14419     CONTRACT(idMethodSpec)
14420     {
14421         NOTHROW;
14422         GC_NOTRIGGER;
14423         MODE_ANY;
14424         PRECONDITION( md != NULL );
14425     }
14426     CONTRACT_END;
14427
14428     idMethodSpec result = idMethodSpecNil;
14429
14430     if (m_nativeImageProfiling)
14431     {
14432         CONTRACT_VIOLATION(ThrowsViolation|FaultViolation|GCViolation);
14433
14434         // get data
14435         SigBuilder sigBuilder;
14436
14437         BOOL fSuccess;
14438         fSuccess = ZapSig::EncodeMethod(const_cast<MethodDesc *>(md), this, &sigBuilder,
14439                                       (LPVOID) this,
14440                        (ENCODEMODULE_CALLBACK) Module::EncodeModuleHelper,
14441                         (DEFINETOKEN_CALLBACK) Module::TokenDefinitionHelper);
14442
14443         if (fSuccess)
14444         {
14445             DWORD dataSize;
14446             BYTE * pBlob = (BYTE *)sigBuilder.GetSignature(&dataSize);
14447
14448             ULONG flag = (1 << flagNum);
14449             MethodSpecBlobEntry *  pEntry = const_cast<MethodSpecBlobEntry *>(MethodSpecBlobEntry::FindOrAdd(this, dataSize, pBlob));
14450             if (pEntry != NULL)
14451             {
14452                 // Update the flags with any new bits
14453                 pEntry->orFlag(flag);
14454                 result = pEntry->token();
14455             }
14456         }
14457     }
14458
14459     _ASSERTE(TypeFromToken(result) == ibcMethodSpec);
14460     RETURN result;
14461 }
14462 #endif // DACCESS_COMPILE
14463 #endif //FEATURE_PREJIT
14464
14465 #ifndef DACCESS_COMPILE
14466
14467 #ifndef CROSSGEN_COMPILE
14468 // ===========================================================================
14469 // ReflectionModule
14470 // ===========================================================================
14471
14472 /* static */
14473 ReflectionModule *ReflectionModule::Create(Assembly *pAssembly, PEFile *pFile, AllocMemTracker *pamTracker, LPCWSTR szName, BOOL fIsTransient)
14474 {
14475     CONTRACT(ReflectionModule *)
14476     {
14477         STANDARD_VM_CHECK;
14478         PRECONDITION(CheckPointer(pAssembly));
14479         PRECONDITION(CheckPointer(pFile));
14480         PRECONDITION(pFile->IsDynamic());
14481         POSTCONDITION(CheckPointer(RETVAL));
14482     }
14483     CONTRACT_END;
14484
14485     // Hoist CONTRACT into separate routine because of EX incompatibility
14486
14487     mdFile token;
14488 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
14489     if (pFile->IsAssembly())
14490         token = mdFileNil;
14491     else
14492         token = ((PEModule *)pFile)->GetToken();
14493 #else
14494     _ASSERTE(pFile->IsAssembly());
14495     token = mdFileNil;
14496 #endif
14497
14498     // Initial memory block for Modules must be zero-initialized (to make it harder
14499     // to introduce Destruct crashes arising from OOM's during initialization.)
14500
14501     void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(ReflectionModule))));
14502     ReflectionModuleHolder pModule(new (pMemory) ReflectionModule(pAssembly, token, pFile));
14503
14504     pModule->DoInit(pamTracker, szName);
14505
14506     // Set this at module creation time. The m_fIsTransient field should never change during the lifetime of this ReflectionModule.
14507     pModule->SetIsTransient(fIsTransient ? true : false);
14508
14509     RETURN pModule.Extract();
14510 }
14511
14512
14513 // Module initialization occurs in two phases: the constructor phase and the Initialize phase.
14514 //
14515 // The constructor phase initializes just enough so that Destruct() can be safely called.
14516 // It cannot throw or fail.
14517 //
14518 ReflectionModule::ReflectionModule(Assembly *pAssembly, mdFile token, PEFile *pFile)
14519   : Module(pAssembly, token, pFile)
14520 {
14521     CONTRACTL
14522     {
14523         NOTHROW;
14524         GC_TRIGGERS;
14525         FORBID_FAULT;
14526     }
14527     CONTRACTL_END
14528
14529     m_pInMemoryWriter = NULL;
14530     m_sdataSection = NULL;
14531     m_pISymUnmanagedWriter = NULL;
14532     m_pCreatingAssembly = NULL;
14533     m_pCeeFileGen = NULL;
14534     m_pDynamicMetadata = NULL;
14535     m_fSuppressMetadataCapture = false;
14536     m_fIsTransient = false;
14537 }
14538
14539 HRESULT STDMETHODCALLTYPE CreateICeeGen(REFIID riid, void **pCeeGen);
14540
14541 // Module initialization occurs in two phases: the constructor phase and the Initialize phase.
14542 //
14543 // The Initialize() phase completes the initialization after the constructor has run.
14544 // It can throw exceptions but whether it throws or succeeds, it must leave the Module
14545 // in a state where Destruct() can be safely called.
14546 //
14547 void ReflectionModule::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName)
14548 {
14549     CONTRACTL
14550     {
14551         INSTANCE_CHECK;
14552         STANDARD_VM_CHECK;
14553         PRECONDITION(szName != NULL);
14554     }
14555     CONTRACTL_END;
14556
14557     Module::Initialize(pamTracker);
14558
14559     IfFailThrow(CreateICeeGen(IID_ICeeGen, (void **)&m_pCeeFileGen));
14560
14561     // Collectible modules should try to limit the growth of their associate IL section, as common scenarios for collectible
14562     // modules include single type modules
14563     if (IsCollectible())
14564     {
14565         ReleaseHolder<ICeeGenInternal> pCeeGenInternal(NULL);
14566         IfFailThrow(m_pCeeFileGen->QueryInterface(IID_ICeeGenInternal, (void **)&pCeeGenInternal));
14567         IfFailThrow(pCeeGenInternal->SetInitialGrowth(CEE_FILE_GEN_GROWTH_COLLECTIBLE));
14568     }
14569
14570     m_pInMemoryWriter = new RefClassWriter();
14571
14572     IfFailThrow(m_pInMemoryWriter->Init(GetCeeGen(), GetEmitter(), szName));
14573
14574     m_CrstLeafLock.Init(CrstLeafLock);
14575 }
14576
14577 void ReflectionModule::Destruct()
14578 {
14579     CONTRACTL
14580     {
14581         NOTHROW;
14582         GC_TRIGGERS;
14583         MODE_PREEMPTIVE;
14584     }
14585     CONTRACTL_END;
14586
14587     delete m_pInMemoryWriter;
14588
14589     if (m_pISymUnmanagedWriter)
14590     {
14591         m_pISymUnmanagedWriter->Close();
14592         m_pISymUnmanagedWriter->Release();
14593         m_pISymUnmanagedWriter = NULL;
14594     }
14595
14596     if (m_pCeeFileGen)
14597         m_pCeeFileGen->Release();
14598
14599     Module::Destruct();
14600
14601     delete m_pDynamicMetadata;
14602     m_pDynamicMetadata = NULL;
14603
14604     m_CrstLeafLock.Destroy();
14605 }
14606
14607 // Returns true iff metadata capturing is suppressed.
14608 // 
14609 // Notes:
14610 //   This is during the window after code:ReflectionModule.SuppressMetadataCapture and before 
14611 //   code:ReflectionModule.ResumeMetadataCapture.
14612 //   
14613 //   If metadata updates are suppressed, then class-load notifications should be suppressed too.
14614 bool ReflectionModule::IsMetadataCaptureSuppressed()
14615 {
14616     return m_fSuppressMetadataCapture;
14617 }
14618 // 
14619 // Holder of changed value of MDUpdateMode via IMDInternalEmit::SetMDUpdateMode.
14620 // Returns back the original value on release.
14621 // 
14622 class MDUpdateModeHolder
14623 {
14624 public:
14625     MDUpdateModeHolder()
14626     {
14627         m_pInternalEmitter = NULL;
14628         m_OriginalMDUpdateMode = ULONG_MAX;
14629     }
14630     ~MDUpdateModeHolder()
14631     {
14632         WRAPPER_NO_CONTRACT;
14633         (void)Release();
14634     }
14635     HRESULT SetMDUpdateMode(IMetaDataEmit *pEmitter, ULONG updateMode)
14636     {
14637         LIMITED_METHOD_CONTRACT;
14638         HRESULT hr = S_OK;
14639         
14640         _ASSERTE(updateMode != ULONG_MAX);
14641         
14642         IfFailRet(pEmitter->QueryInterface(IID_IMDInternalEmit, (void **)&m_pInternalEmitter));
14643         _ASSERTE(m_pInternalEmitter != NULL);
14644         
14645         IfFailRet(m_pInternalEmitter->SetMDUpdateMode(updateMode, &m_OriginalMDUpdateMode));
14646         _ASSERTE(m_OriginalMDUpdateMode != ULONG_MAX);
14647         
14648         return hr;
14649     }
14650     HRESULT Release(ULONG expectedPreviousUpdateMode = ULONG_MAX)
14651     {
14652         HRESULT hr = S_OK;
14653         
14654         if (m_OriginalMDUpdateMode != ULONG_MAX)
14655         {
14656             _ASSERTE(m_pInternalEmitter != NULL);
14657             ULONG previousUpdateMode;
14658             // Ignore the error when releasing
14659             hr = m_pInternalEmitter->SetMDUpdateMode(m_OriginalMDUpdateMode, &previousUpdateMode);
14660             m_OriginalMDUpdateMode = ULONG_MAX;
14661             
14662             if (expectedPreviousUpdateMode != ULONG_MAX)
14663             {
14664                 if ((hr == S_OK) && (expectedPreviousUpdateMode != previousUpdateMode))
14665                 {
14666                     hr = S_FALSE;
14667                 }
14668             }
14669         }
14670         if (m_pInternalEmitter != NULL)
14671         {
14672             (void)m_pInternalEmitter->Release();
14673             m_pInternalEmitter = NULL;
14674         }
14675         return hr;
14676     }
14677     ULONG GetOriginalMDUpdateMode()
14678     {
14679         WRAPPER_NO_CONTRACT;
14680         _ASSERTE(m_OriginalMDUpdateMode != LONG_MAX);
14681         return m_OriginalMDUpdateMode;
14682     }
14683 private:
14684     IMDInternalEmit *m_pInternalEmitter;
14685     ULONG            m_OriginalMDUpdateMode;
14686 };
14687
14688 // Called in live paths to fetch metadata for dynamic modules. This makes the metadata available to the
14689 // debugger from out-of-process.
14690 // 
14691 // Notes:
14692 //    This buffer can be retrieved by the debugger via code:ReflectionModule.GetDynamicMetadataBuffer 
14693 //    
14694 //    Threading:
14695 //    - Callers must ensure nobody else is adding to the metadata.
14696 //    - This function still takes its own locks to cooperate with the Debugger's out-of-process access.
14697 //      The debugger can slip this thread outside the locks to ensure the data is consistent.
14698 //    
14699 //    This does not raise a debug notification to invalidate the metadata. Reasoning is that this only
14700 //    happens in two cases:
14701 //    1) manifest module is updated with the name of a new dynamic module. 
14702 //    2) on each class load, in which case we already send a debug event. In this case, we already send a
14703 //    class-load notification, so sending a separate "metadata-refresh" would make the eventing twice as
14704 //    chatty. Class-load events are high-volume and events are slow.
14705 //    Thus we can avoid the chatiness by ensuring the debugger knows that Class-load also means "refresh
14706 //    metadata".
14707 //    
14708 void ReflectionModule::CaptureModuleMetaDataToMemory()
14709 {
14710     CONTRACTL
14711     {
14712         THROWS;
14713         GC_TRIGGERS;
14714     }
14715     CONTRACTL_END;
14716
14717     // If we've suppresed metadata capture, then skip this. We'll recapture when we enable it. This allows
14718     // for batching up capture.
14719     // If a debugger is attached, then the CLR will still send ClassLoad notifications for dynamic modules,
14720     // which mean we still need to keep the metadata available. This is the same as Whidbey.
14721     // An alternative (and better) design would be to suppress ClassLoad notifications too, but then we'd
14722     // need some way of sending a "catchup" notification to the debugger after we re-enable notifications. 
14723     if (IsMetadataCaptureSuppressed() && !CORDebuggerAttached())
14724     {
14725         return;
14726     }
14727
14728     // Do not release the emitter. This is a weak reference.
14729     IMetaDataEmit *pEmitter = this->GetEmitter();
14730     _ASSERTE(pEmitter != NULL);
14731
14732     HRESULT hr;
14733     
14734     MDUpdateModeHolder hMDUpdateMode;
14735     IfFailThrow(hMDUpdateMode.SetMDUpdateMode(pEmitter, MDUpdateExtension));
14736     _ASSERTE(hMDUpdateMode.GetOriginalMDUpdateMode() == MDUpdateFull);
14737     
14738     DWORD numBytes;
14739     hr = pEmitter->GetSaveSize(cssQuick, &numBytes);
14740     IfFailThrow(hr);
14741
14742     // Operate on local data, and then persist it into the module once we know it's valid.
14743     NewHolder<SBuffer> pBuffer(new SBuffer());
14744     _ASSERTE(pBuffer != NULL); // allocation would throw first
14745
14746     // ReflectionModule is still in a consistent state, and now we're just operating on local data to
14747     // assemble the new metadata buffer. If this fails, then worst case is that metadata does not include
14748     // recently generated classes.
14749     
14750     // Caller ensures serialization that guarantees that the metadata doesn't grow underneath us.
14751     BYTE * pRawData = pBuffer->OpenRawBuffer(numBytes);
14752     hr = pEmitter->SaveToMemory(pRawData, numBytes);
14753     pBuffer->CloseRawBuffer();
14754
14755     IfFailThrow(hr);
14756     
14757     // Now that we're successful, transfer ownership back into the module.
14758     {
14759         CrstHolder ch(&m_CrstLeafLock);
14760
14761         delete m_pDynamicMetadata;
14762         
14763         m_pDynamicMetadata = pBuffer.Extract();
14764     }
14765
14766     // 
14767     
14768     hr = hMDUpdateMode.Release(MDUpdateExtension);
14769     // Will be S_FALSE if someone changed the MDUpdateMode (from MDUpdateExtension) meanwhile
14770     _ASSERTE(hr == S_OK);
14771 }
14772
14773 // Suppress the eager metadata serialization.
14774 // 
14775 // Notes:
14776 //    This casues code:ReflectionModule.CaptureModuleMetaDataToMemory to be a nop.
14777 //    This is not nestable.
14778 //    This exists purely for performance reasons. 
14779 //    
14780 //    Don't call this directly. Use a SuppressMetadataCaptureHolder holder to ensure it's 
14781 //    balanced with code:ReflectionModule.ResumeMetadataCapture
14782 //    
14783 //    Types generating while eager metadata-capture is suppressed should not actually be executed until
14784 //    after metadata capture is restored.
14785 void ReflectionModule::SuppressMetadataCapture()
14786 {
14787     LIMITED_METHOD_CONTRACT;
14788     // If this fires, then you probably missed a call to ResumeMetadataCapture.
14789     CONSISTENCY_CHECK_MSG(!m_fSuppressMetadataCapture, "SuppressMetadataCapture is not nestable");
14790     m_fSuppressMetadataCapture = true;
14791 }
14792
14793 // Resumes eager metadata serialization.
14794 // 
14795 // Notes:
14796 //    This casues code:ReflectionModule.CaptureModuleMetaDataToMemory to resume eagerly serializing metadata.
14797 //    This must be called after code:ReflectionModule.SuppressMetadataCapture.
14798 //    
14799 void ReflectionModule::ResumeMetadataCapture()
14800 {
14801     WRAPPER_NO_CONTRACT;
14802     _ASSERTE(m_fSuppressMetadataCapture);
14803     m_fSuppressMetadataCapture = false;
14804     
14805     CaptureModuleMetaDataToMemory();
14806 }
14807
14808 void ReflectionModule::ReleaseILData()
14809 {
14810     WRAPPER_NO_CONTRACT;
14811
14812     if (m_pISymUnmanagedWriter)
14813     {
14814         m_pISymUnmanagedWriter->Release();
14815         m_pISymUnmanagedWriter = NULL;
14816     }
14817
14818     Module::ReleaseILData();
14819 }
14820 #endif // !CROSSGEN_COMPILE
14821
14822 #endif // !DACCESS_COMPILE
14823
14824 #ifdef DACCESS_COMPILE
14825 // Accessor to expose m_pDynamicMetadata to debugger.
14826 // 
14827 // Returns:
14828 //    Pointer to SBuffer  containing metadata buffer. May be null.
14829 //    
14830 // Notes:
14831 //    Only used by the debugger, so only accessible via DAC.
14832 //    The buffer is updated via code:ReflectionModule.CaptureModuleMetaDataToMemory
14833 PTR_SBuffer ReflectionModule::GetDynamicMetadataBuffer() const
14834 {
14835     SUPPORTS_DAC;
14836
14837     // If we ask for metadata, but have been suppressing capture, then we're out of date.
14838     // However, the debugger may be debugging already baked types in the module and so may need the metadata
14839     // for that. So we return what we do have. 
14840     // 
14841     // Debugger will get the next metadata update:
14842     // 1) with the next load class
14843     // 2) or if this is right after the last class, see code:ReflectionModule.CaptureModuleMetaDataToMemory
14844
14845     return m_pDynamicMetadata; 
14846 }
14847 #endif
14848
14849 TADDR ReflectionModule::GetIL(RVA il) // virtual
14850 {
14851 #ifndef DACCESS_COMPILE 
14852     WRAPPER_NO_CONTRACT;
14853
14854     BYTE* pByte = NULL;
14855     m_pCeeFileGen->GetMethodBuffer(il, &pByte);
14856     return TADDR(pByte);
14857 #else // DACCESS_COMPILE
14858     SUPPORTS_DAC;
14859     DacNotImpl();
14860     return NULL;
14861 #endif // DACCESS_COMPILE
14862 }
14863
14864 PTR_VOID ReflectionModule::GetRvaField(RVA field, BOOL fZapped) // virtual
14865 {
14866     _ASSERTE(!fZapped);
14867 #ifndef DACCESS_COMPILE 
14868     WRAPPER_NO_CONTRACT;
14869     // This function should be call only if the target is a field or a field with RVA.
14870     PTR_BYTE pByte = NULL;
14871     m_pCeeFileGen->ComputePointer(m_sdataSection, field, &pByte);
14872     return dac_cast<PTR_VOID>(pByte);
14873 #else // DACCESS_COMPILE
14874     SUPPORTS_DAC;
14875     DacNotImpl();
14876     return NULL;
14877 #endif // DACCESS_COMPILE
14878 }
14879
14880 #ifndef DACCESS_COMPILE 
14881
14882 // ===========================================================================
14883 // VASigCookies
14884 // ===========================================================================
14885
14886 //==========================================================================
14887 // Enregisters a VASig.
14888 //==========================================================================
14889 VASigCookie *Module::GetVASigCookie(Signature vaSignature)
14890 {
14891     CONTRACT(VASigCookie*)
14892     {
14893         INSTANCE_CHECK;
14894         THROWS;
14895         GC_TRIGGERS;
14896         MODE_ANY;
14897         POSTCONDITION(CheckPointer(RETVAL));
14898         INJECT_FAULT(COMPlusThrowOM());
14899     }
14900     CONTRACT_END;
14901
14902     VASigCookieBlock *pBlock;
14903     VASigCookie      *pCookie;
14904
14905     pCookie = NULL;
14906
14907     // First, see if we already enregistered this sig.
14908     // Note that we're outside the lock here, so be a bit careful with our logic
14909     for (pBlock = m_pVASigCookieBlock; pBlock != NULL; pBlock = pBlock->m_Next)
14910     {
14911         for (UINT i = 0; i < pBlock->m_numcookies; i++)
14912         {
14913             if (pBlock->m_cookies[i].signature.GetRawSig() == vaSignature.GetRawSig())
14914             {
14915                 pCookie = &(pBlock->m_cookies[i]);
14916                 break;
14917             }
14918         }
14919     }
14920
14921     if (!pCookie)
14922     {
14923         // If not, time to make a new one.
14924
14925         // Compute the size of args first, outside of the lock.
14926
14927         // @TODO GENERICS: We may be calling a varargs method from a 
14928         // generic type/method. Using an empty context will make such a 
14929         // case cause an unexpected exception. To make this work, 
14930         // we need to create a specialized signature for every instantiation
14931         SigTypeContext typeContext;
14932
14933         MetaSig metasig(vaSignature, this, &typeContext);
14934         ArgIterator argit(&metasig);
14935
14936         // Upper estimate of the vararg size
14937         DWORD sizeOfArgs = argit.SizeOfArgStack();
14938
14939         // enable gc before taking lock
14940         {
14941             CrstHolder ch(&m_Crst);
14942
14943             // Note that we were possibly racing to create the cookie, and another thread
14944             // may have already created it.  We could put another check
14945             // here, but it's probably not worth the effort, so we'll just take an
14946             // occasional duplicate cookie instead.
14947
14948             // Is the first block in the list full?
14949             if (m_pVASigCookieBlock && m_pVASigCookieBlock->m_numcookies
14950                 < VASigCookieBlock::kVASigCookieBlockSize)
14951             {
14952                 // Nope, reserve a new slot in the existing block.
14953                 pCookie = &(m_pVASigCookieBlock->m_cookies[m_pVASigCookieBlock->m_numcookies]);
14954             }
14955             else
14956             {
14957                 // Yes, create a new block.
14958                 VASigCookieBlock *pNewBlock = new VASigCookieBlock();
14959
14960                 pNewBlock->m_Next = m_pVASigCookieBlock;
14961                 pNewBlock->m_numcookies = 0;
14962                 m_pVASigCookieBlock = pNewBlock;
14963                 pCookie = &(pNewBlock->m_cookies[0]);
14964             }
14965
14966             // Now, fill in the new cookie (assuming we had enough memory to create one.)
14967             pCookie->pModule = this;
14968             pCookie->pNDirectILStub = NULL;
14969             pCookie->sizeOfArgs = sizeOfArgs;
14970             pCookie->signature = vaSignature;
14971
14972             // Finally, now that it's safe for ansynchronous readers to see it,
14973             // update the count.
14974             m_pVASigCookieBlock->m_numcookies++;
14975         }
14976     }
14977
14978     RETURN pCookie;
14979 }
14980
14981 // ===========================================================================
14982 // LookupMap
14983 // ===========================================================================
14984 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
14985
14986 int __cdecl LookupMapBase::HotItem::Cmp(const void* a_, const void* b_)
14987 {
14988     LIMITED_METHOD_CONTRACT;
14989     const HotItem *a = (const HotItem *)a_;
14990     const HotItem *b = (const HotItem *)b_;
14991
14992     if (a->rid < b->rid)
14993         return -1;
14994     else if (a->rid > b->rid)
14995         return 1;
14996     else
14997         return 0;
14998 }
14999
15000 void LookupMapBase::CreateHotItemList(DataImage *image, CorProfileData *profileData, int table, BOOL fSkipNullEntries /*= FALSE*/)
15001 {
15002     STANDARD_VM_CONTRACT;
15003     _ASSERTE(!MapIsCompressed());
15004
15005     if (profileData)
15006     {
15007         DWORD numInTokenList = profileData->GetHotTokens(table, 1<<RidMap, 1<<RidMap, NULL, 0);
15008         
15009         if (numInTokenList > 0)
15010         {
15011             HotItem *itemList = (HotItem*)(void*)image->GetModule()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(HotItem)) * S_SIZE_T(numInTokenList));
15012             mdToken *tokenList = (mdToken*)(void*)image->GetModule()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(mdToken)) * S_SIZE_T(numInTokenList));
15013
15014             profileData->GetHotTokens(table, 1<<RidMap, 1<<RidMap, tokenList, numInTokenList);
15015             DWORD numItems = 0;
15016             for (DWORD i = 0; i < numInTokenList; i++)
15017             {
15018                 DWORD rid = RidFromToken(tokenList[i]);
15019                 TADDR value = RelativePointer<TADDR>::GetValueMaybeNullAtPtr(dac_cast<TADDR>(GetElementPtr(RidFromToken(tokenList[i]))));
15020                 if (!fSkipNullEntries || value != NULL)
15021                 {
15022                     itemList[numItems].rid = rid;
15023                     itemList[numItems].value = value;
15024                     ++numItems;
15025                 }
15026             }
15027
15028             if (numItems > 0)
15029             {
15030                 qsort(itemList,          // start of array
15031                       numItems,          // array size in elements
15032                       sizeof(HotItem),      // element size in bytes
15033                       HotItem::Cmp);        // comparer function
15034
15035                 // Eliminate any duplicates in the list. Due to the qsort, they must be adjacent now.
15036                 // We do this by walking the array and copying entries that are not duplicates of the previous one.
15037                 // We can start the loop at +1, because 0 is not a duplicate of the previous entry, and does not
15038                 // need to be copied either.
15039                 DWORD j = 1;
15040                 for (DWORD i = 1; i < numItems; i++)
15041                 {
15042                     if (itemList[i].rid != itemList[i-1].rid)
15043                     {
15044                         itemList[j].rid   = itemList[i].rid;
15045                         itemList[j].value = itemList[i].value;
15046                         j++;
15047                     }
15048                 }
15049                 _ASSERTE(j <= numItems);
15050                 numItems = j;
15051
15052                 // We have treated the values as normal TADDRs to let qsort move them around freely.
15053                 // Fix them up to be the relative pointers now.
15054                 for (DWORD ii = 0; ii < numItems; ii++)
15055                 {
15056                     if (itemList[ii].value != NULL)
15057                         RelativePointer<TADDR>::SetValueMaybeNullAtPtr(dac_cast<TADDR>(&itemList[ii].value), itemList[ii].value);
15058                 }
15059
15060                 if (itemList != NULL)
15061                     image->StoreStructure(itemList, sizeof(HotItem)*numItems,
15062                                           DataImage::ITEM_RID_MAP_HOT);
15063
15064                 hotItemList = itemList;
15065                 dwNumHotItems = numItems;
15066             }
15067         }
15068     }
15069 }
15070
15071 void LookupMapBase::Save(DataImage *image, DataImage::ItemKind kind, CorProfileData *profileData, int table, BOOL fCopyValues /*= FALSE*/)
15072 {
15073     STANDARD_VM_CONTRACT;
15074
15075     // 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
15076     table >>= 24;
15077
15078     dwNumHotItems = 0;
15079     hotItemList = NULL;
15080
15081     if (table != 0)
15082     {
15083         // Because we use the same IBC encoding to record a touch to the m_GenericTypeDefToCanonMethodTableMap as
15084         // to the m_TypeDefToMethodTableMap, the hot items we get in both will be the union of the touches.  This limitation
15085         // in the IBC infrastructure does not hurt us much because touching an entry for a generic type in one map often if
15086         // not always implies touching the corresponding entry in the other.  But when saving the GENERICTYPEDEF_MAP it
15087         // does mean that we need to be prepared to see "hot" items whose data is NULL in this map (specifically, the non-
15088         // generic types).  We don't want the hot list to be unnecessarily big with these entries, so tell CreateHotItemList to
15089         // skip them.
15090         BOOL fSkipNullEntries = (kind == DataImage::ITEM_GENERICTYPEDEF_MAP);
15091         CreateHotItemList(image, profileData, table, fSkipNullEntries);
15092     }
15093
15094     // Determine whether we want to compress this lookup map (to improve density of cold pages in the map on
15095     // hot item cache misses). We only enable this optimization for the TypeDefToMethodTable, the 
15096     // GenericTypeDefToCanonMethodTable, and the MethodDefToDesc maps since (a) they're the largest and 
15097     // as a result reap the most space savings and (b) these maps are fully populated in an ngen image and immutable 
15098     // at runtime, something that's important when dealing with a compressed version of the table.
15099     if (kind == DataImage::ITEM_TYPEDEF_MAP || kind == DataImage::ITEM_GENERICTYPEDEF_MAP || kind == DataImage::ITEM_METHODDEF_MAP)
15100     {
15101         // The bulk of the compression work is done in the later stages of ngen image generation (since it
15102         // relies on knowing the final RVAs of each value stored in the table). So we create a specialzed
15103         // ZapNode that knows how to perform the compression for us.
15104         image->StoreCompressedLayoutMap(this, DataImage::ITEM_COMPRESSED_MAP);
15105
15106         // We need to know we decided to compress during the Fixup stage but the table kind is not available
15107         // there. So we use the cIndexEntryBits field as a flag (this will be initialized to zero and is only
15108         // set to a meaningful value near the end of ngen image generation, during the compression of the
15109         // table itself).
15110         cIndexEntryBits = 1;
15111
15112         // The ZapNode we allocated above takes care of all the rest of the processing for this map, so we're
15113         // done here.
15114         return;
15115     }
15116
15117     SaveUncompressedMap(image, kind, fCopyValues);
15118 }
15119
15120 void LookupMapBase::SaveUncompressedMap(DataImage *image, DataImage::ItemKind kind, BOOL fCopyValues /*= FALSE*/)
15121 {
15122     STANDARD_VM_CONTRACT;
15123
15124     // We should only be calling this once per map
15125     _ASSERTE(!image->IsStored(pTable));
15126
15127     //
15128     // We will only store one (big) node instead of the full list,
15129     // and make the one node large enough to fit all the RIDs
15130     //
15131
15132     ZapStoredStructure * pTableNode = image->StoreStructure(NULL, GetSize() * sizeof(TADDR), kind);
15133
15134     LookupMapBase *map = this;
15135     DWORD offsetIntoCombo = 0;
15136     while (map != NULL)
15137     {
15138         DWORD len = map->dwCount * sizeof(void*);
15139
15140         if (fCopyValues)
15141             image->CopyDataToOffset(pTableNode, offsetIntoCombo, map->pTable, len);
15142
15143         image->BindPointer(map->pTable,pTableNode,offsetIntoCombo);
15144         offsetIntoCombo += len;
15145         map = map->pNext;
15146     }
15147 }
15148
15149 void LookupMapBase::ConvertSavedMapToUncompressed(DataImage *image, DataImage::ItemKind kind)
15150 {
15151     STANDARD_VM_CONTRACT;
15152
15153     // Check whether we decided to compress this map (see Save() above).
15154     if (cIndexEntryBits == 0)
15155         return;
15156
15157     cIndexEntryBits = 0;
15158     SaveUncompressedMap(image, kind);
15159 }
15160
15161 void LookupMapBase::Fixup(DataImage *image, BOOL fFixupEntries /*=TRUE*/)
15162 {
15163     STANDARD_VM_CONTRACT;
15164
15165     if (hotItemList != NULL)
15166         image->FixupPointerField(this, offsetof(LookupMapBase, hotItemList));
15167
15168     // Find the biggest RID supported by the entire list of LookupMaps.
15169     // We will only store one LookupMap node instead of the full list,
15170     // and make it big enough to fit all RIDs.
15171     *(DWORD *)image->GetImagePointer(this, offsetof(LookupMapBase, dwCount)) = GetSize();
15172
15173     // Persist the supportedFlags that this particular instance was created with.
15174     *(TADDR *)image->GetImagePointer(this, offsetof(LookupMapBase, supportedFlags)) = supportedFlags;
15175
15176     image->ZeroPointerField(this, offsetof(LookupMapBase, pNext));
15177
15178     // Check whether we've decided to compress this map (see Save() above).
15179     if (cIndexEntryBits == 1)
15180     {
15181         // In the compressed case most of the Fixup logic is performed by the specialized ZapNode we allocated
15182         // during Save(). But we still have to record fixups for any hot items we've cached (these aren't
15183         // compressed).
15184         for (DWORD i = 0; i < dwNumHotItems; i++)
15185         {
15186             TADDR *pHotValueLoc = &hotItemList[i].value;
15187             TADDR pHotValue = RelativePointer<TADDR>::GetValueMaybeNullAtPtr((TADDR)pHotValueLoc);
15188             TADDR flags = pHotValue & supportedFlags;
15189             pHotValue -= flags;
15190
15191             if (image->IsStored((PVOID)pHotValue))
15192             {
15193                 image->FixupField(hotItemList,
15194                                   (BYTE *)pHotValueLoc - (BYTE *)hotItemList,
15195                                   (PVOID)pHotValue, flags, IMAGE_REL_BASED_RelativePointer);
15196             }
15197             else
15198             {
15199                 image->ZeroPointerField(hotItemList, (BYTE *)pHotValueLoc - (BYTE *)hotItemList);
15200             }
15201         }
15202
15203         // The ZapNode will handle everything else so we're done.
15204         return;
15205     }
15206
15207     // Note that the caller is responsible for calling FixupPointerField()
15208     // or zeroing out the contents of pTable as appropriate
15209     image->FixupPointerField(this, offsetof(LookupMapBase, pTable));
15210
15211     if (fFixupEntries)
15212     {
15213         LookupMap<PVOID>::Iterator iter((LookupMap<PVOID> *)this);
15214         DWORD rid = 0;
15215
15216         while (iter.Next())
15217         {
15218             TADDR flags;
15219             PVOID p = iter.GetElementAndFlags(&flags);
15220             PTR_TADDR hotItemValuePtr = FindHotItemValuePtr(rid);
15221
15222             if (image->IsStored(p))
15223             {
15224                 image->FixupField(pTable, rid * sizeof(TADDR),
15225                     p, flags, IMAGE_REL_BASED_RelativePointer);
15226
15227                 // In case this item is also in the hot item subtable, fix it up there as well
15228                 if (hotItemValuePtr != NULL)
15229                     image->FixupField(hotItemList,
15230                         (BYTE *)hotItemValuePtr - (BYTE *)hotItemList,
15231                         p, flags, IMAGE_REL_BASED_RelativePointer);
15232             }
15233             else
15234             {
15235                 image->ZeroPointerField(pTable, rid * sizeof(TADDR));
15236                 // In case this item is also in the hot item subtable, zero it there as well
15237                 if (hotItemValuePtr != NULL)
15238                     image->ZeroPointerField(hotItemList, 
15239                         (BYTE *)hotItemValuePtr - (BYTE *)hotItemList);
15240             }
15241
15242             rid++;
15243         }
15244     }
15245 }
15246 #endif // FEATURE_NATIVE_IMAGE_GENERATION
15247
15248 #endif // !DACCESS_COMPILE
15249
15250 #ifdef DACCESS_COMPILE 
15251
15252 void
15253 LookupMapBase::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
15254                              bool enumThis)
15255 {
15256     CONTRACTL
15257     {
15258         INSTANCE_CHECK;
15259         NOTHROW;
15260         GC_NOTRIGGER;
15261         MODE_ANY;
15262         FORBID_FAULT;
15263         SUPPORTS_DAC;
15264     }
15265     CONTRACTL_END;
15266
15267     if (enumThis)
15268     {
15269         DacEnumHostDPtrMem(this);
15270     }
15271     if (pTable.IsValid())
15272     {
15273 #ifdef FEATURE_PREJIT
15274         if (MapIsCompressed())
15275         {
15276             // Compressed maps have tables whose size cannot be calculated cheaply. Plus they have an
15277             // additional index blob.
15278             DacEnumMemoryRegion(dac_cast<TADDR>(pTable),
15279                                 cbTable);
15280             DacEnumMemoryRegion(dac_cast<TADDR>(pIndex),
15281                                 cbIndex);
15282         }
15283         else
15284 #endif // FEATURE_PREJIT
15285             DacEnumMemoryRegion(dac_cast<TADDR>(pTable),
15286                                 dwCount * sizeof(TADDR));
15287     }
15288 #ifdef FEATURE_PREJIT 
15289     if (dwNumHotItems && hotItemList.IsValid())
15290     {
15291         DacEnumMemoryRegion(dac_cast<TADDR>(hotItemList),
15292                             dwNumHotItems * sizeof(HotItem));
15293     }
15294 #endif // FEATURE_PREJIT
15295 }
15296
15297
15298 /* static */
15299 void
15300 LookupMapBase::ListEnumMemoryRegions(CLRDataEnumMemoryFlags flags)
15301 {
15302     CONTRACTL
15303     {
15304         NOTHROW;
15305         GC_NOTRIGGER;
15306         MODE_ANY;
15307         FORBID_FAULT;
15308         SUPPORTS_DAC;
15309     }
15310     CONTRACTL_END;
15311
15312     LookupMapBase * headMap = this;
15313     bool enumHead = false;
15314     while (headMap)
15315     {
15316         headMap->EnumMemoryRegions(flags, enumHead);
15317
15318         if (!headMap->pNext.IsValid())
15319         {
15320             break;
15321         }
15322
15323         headMap = headMap->pNext;
15324         enumHead = true;
15325     }
15326 }
15327
15328 #endif // DACCESS_COMPILE
15329
15330
15331 // Optimization intended for Module::IsIntrospectionOnly and Module::EnsureActive only
15332 #include <optsmallperfcritical.h>
15333
15334 BOOL Module::IsIntrospectionOnly()
15335 {
15336     WRAPPER_NO_CONTRACT;
15337     return GetAssembly()->IsIntrospectionOnly();
15338 }
15339
15340 #ifndef DACCESS_COMPILE
15341 VOID Module::EnsureActive()
15342 {
15343     CONTRACTL
15344     {
15345         THROWS;
15346         GC_TRIGGERS;
15347         MODE_ANY;
15348     }
15349     CONTRACTL_END;
15350     GetDomainFile()->EnsureActive();
15351 }
15352 #endif // DACCESS_COMPILE
15353
15354 #include <optdefault.h>
15355
15356
15357 #ifndef DACCESS_COMPILE
15358
15359 VOID Module::EnsureAllocated()
15360 {
15361     CONTRACTL
15362     {
15363         THROWS;
15364         GC_TRIGGERS;
15365         MODE_ANY;
15366     }
15367     CONTRACTL_END;
15368
15369     GetDomainFile()->EnsureAllocated();
15370 }
15371
15372 VOID Module::EnsureLibraryLoaded()
15373 {
15374     STANDARD_VM_CONTRACT;
15375     GetDomainFile()->EnsureLibraryLoaded();
15376 }
15377 #endif // !DACCESS_COMPILE
15378
15379 CHECK Module::CheckActivated()
15380 {
15381     CONTRACTL
15382     {
15383         NOTHROW;
15384         GC_NOTRIGGER;
15385         MODE_ANY;
15386     }
15387     CONTRACTL_END;
15388
15389 #ifndef DACCESS_COMPILE 
15390     DomainFile *pDomainFile = FindDomainFile(GetAppDomain());
15391     CHECK(pDomainFile != NULL);
15392     PREFIX_ASSUME(pDomainFile != NULL);
15393     CHECK(pDomainFile->CheckActivated());
15394 #endif
15395     CHECK_OK;
15396 }
15397
15398 #ifdef DACCESS_COMPILE 
15399
15400 void
15401 ModuleCtorInfo::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
15402 {
15403     SUPPORTS_DAC;
15404
15405     // This class is contained so do not enumerate 'this'.
15406     DacEnumMemoryRegion(dac_cast<TADDR>(ppMT), numElements *
15407                         sizeof(TADDR));
15408     DacEnumMemoryRegion(dac_cast<TADDR>(cctorInfoHot), numElementsHot *
15409                         sizeof(ClassCtorInfoEntry));
15410     DacEnumMemoryRegion(dac_cast<TADDR>(cctorInfoCold),
15411                         (numElements - numElementsHot) *
15412                         sizeof(ClassCtorInfoEntry));
15413     DacEnumMemoryRegion(dac_cast<TADDR>(hotHashOffsets), numHotHashes *
15414                         sizeof(DWORD));
15415     DacEnumMemoryRegion(dac_cast<TADDR>(coldHashOffsets), numColdHashes *
15416                         sizeof(DWORD));
15417 }
15418
15419 void Module::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
15420                                bool enumThis)
15421 {
15422     CONTRACTL
15423     {
15424         INSTANCE_CHECK;
15425         NOTHROW;
15426         GC_NOTRIGGER;
15427         MODE_ANY;
15428         FORBID_FAULT;
15429         SUPPORTS_DAC;
15430     }
15431     CONTRACTL_END;
15432
15433     if (enumThis)
15434     {
15435         DAC_ENUM_VTHIS();
15436         EMEM_OUT(("MEM: %p Module\n", dac_cast<TADDR>(this)));
15437     }
15438
15439     //Save module id data only if it a real pointer, not a tagged sugestion to use ModuleIndex.
15440     if (!Module::IsEncodedModuleIndex(GetModuleID()))
15441     {
15442         if (m_ModuleID.IsValid())
15443         {
15444             m_ModuleID->EnumMemoryRegions(flags);
15445         }
15446     }
15447
15448     // TODO: Enumerate DomainLocalModules?  It's not clear if we need all AppDomains 
15449     // in the multi-domain case (where m_ModuleID has it's low-bit set).
15450     if (m_file.IsValid())
15451     {
15452         m_file->EnumMemoryRegions(flags);
15453     }
15454     if (m_pAssembly.IsValid())
15455     {
15456         m_pAssembly->EnumMemoryRegions(flags);
15457     }
15458
15459     m_TypeRefToMethodTableMap.ListEnumMemoryRegions(flags);
15460     m_TypeDefToMethodTableMap.ListEnumMemoryRegions(flags);
15461
15462     if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE)
15463     {
15464         if (m_pAvailableClasses.IsValid())
15465         {
15466             m_pAvailableClasses->EnumMemoryRegions(flags);
15467         }
15468         if (m_pAvailableParamTypes.IsValid())
15469         {
15470             m_pAvailableParamTypes->EnumMemoryRegions(flags);
15471         }
15472         if (m_pInstMethodHashTable.IsValid())
15473         {
15474             m_pInstMethodHashTable->EnumMemoryRegions(flags);
15475         }
15476         if (m_pAvailableClassesCaseIns.IsValid())
15477         {
15478             m_pAvailableClassesCaseIns->EnumMemoryRegions(flags);
15479         }
15480 #ifdef FEATURE_PREJIT
15481         if (m_pStubMethodHashTable.IsValid())
15482         {
15483             m_pStubMethodHashTable->EnumMemoryRegions(flags);
15484         }
15485 #endif // FEATURE_PREJIT
15486 #ifdef FEATURE_MIXEDMODE
15487         if (m_pThunkHeap.IsValid())
15488         {
15489             m_pThunkHeap->EnumMemoryRegions(flags);
15490         }
15491 #endif // FEATURE_MIXEDMODE
15492         if (m_pBinder.IsValid())
15493         {
15494             m_pBinder->EnumMemoryRegions(flags);
15495         }
15496         m_ModuleCtorInfo.EnumMemoryRegions(flags);
15497
15498         // Save the LookupMap structures.
15499         m_MethodDefToDescMap.ListEnumMemoryRegions(flags);
15500         m_FieldDefToDescMap.ListEnumMemoryRegions(flags);
15501         m_pMemberRefToDescHashTable->EnumMemoryRegions(flags);
15502         m_GenericParamToDescMap.ListEnumMemoryRegions(flags);
15503         m_GenericTypeDefToCanonMethodTableMap.ListEnumMemoryRegions(flags);
15504         m_FileReferencesMap.ListEnumMemoryRegions(flags);
15505         m_ManifestModuleReferencesMap.ListEnumMemoryRegions(flags);
15506         m_MethodDefToPropertyInfoMap.ListEnumMemoryRegions(flags);
15507
15508         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
15509         while (typeDefIter.Next())
15510         {
15511             if (typeDefIter.GetElement())
15512             {
15513                 typeDefIter.GetElement()->EnumMemoryRegions(flags);
15514             }
15515         }
15516
15517         LookupMap<PTR_TypeRef>::Iterator typeRefIter(&m_TypeRefToMethodTableMap);
15518         while (typeRefIter.Next())
15519         {
15520             if (typeRefIter.GetElement())
15521             {
15522                 TypeHandle th = TypeHandle::FromTAddr(dac_cast<TADDR>(typeRefIter.GetElement()));
15523                 th.EnumMemoryRegions(flags);
15524             }
15525         }
15526
15527         LookupMap<PTR_MethodDesc>::Iterator methodDefIter(&m_MethodDefToDescMap);
15528         while (methodDefIter.Next())
15529         {
15530             if (methodDefIter.GetElement())
15531             {
15532                 methodDefIter.GetElement()->EnumMemoryRegions(flags);
15533             }
15534         }
15535
15536         LookupMap<PTR_FieldDesc>::Iterator fieldDefIter(&m_FieldDefToDescMap);
15537         while (fieldDefIter.Next())
15538         {
15539             if (fieldDefIter.GetElement())
15540             {
15541                 fieldDefIter.GetElement()->EnumMemoryRegions(flags);
15542             }
15543         }
15544
15545         LookupMap<PTR_TypeVarTypeDesc>::Iterator genericParamIter(&m_GenericParamToDescMap);
15546         while (genericParamIter.Next())
15547         {
15548             if (genericParamIter.GetElement())
15549             {
15550                 genericParamIter.GetElement()->EnumMemoryRegions(flags);
15551             }
15552         }
15553
15554         LookupMap<PTR_MethodTable>::Iterator genericTypeDefIter(&m_GenericTypeDefToCanonMethodTableMap);
15555         while (genericTypeDefIter.Next())
15556         {
15557             if (genericTypeDefIter.GetElement())
15558             {
15559                 genericTypeDefIter.GetElement()->EnumMemoryRegions(flags);
15560             }
15561         }
15562
15563     }   // !CLRDATA_ENUM_MEM_MINI && !CLRDATA_ENUM_MEM_TRIAGE
15564     
15565
15566     LookupMap<PTR_Module>::Iterator fileRefIter(&m_FileReferencesMap);
15567     while (fileRefIter.Next())
15568     {
15569         if (fileRefIter.GetElement())
15570         {
15571             fileRefIter.GetElement()->EnumMemoryRegions(flags, true);
15572         }
15573     }
15574
15575     LookupMap<PTR_Module>::Iterator asmRefIter(&m_ManifestModuleReferencesMap);
15576     while (asmRefIter.Next())
15577     {
15578         if (asmRefIter.GetElement())
15579         {
15580             asmRefIter.GetElement()->GetAssembly()->EnumMemoryRegions(flags);
15581         }
15582     }
15583
15584     ECall::EnumFCallMethods();
15585 }
15586
15587 FieldDesc *Module::LookupFieldDef(mdFieldDef token)
15588 {
15589     WRAPPER_NO_CONTRACT;
15590     _ASSERTE(TypeFromToken(token) == mdtFieldDef);
15591     g_IBCLogger.LogRidMapAccess( MakePair( this, token ) );
15592     return m_FieldDefToDescMap.GetElement(RidFromToken(token));
15593 }
15594
15595 #endif // DACCESS_COMPILE
15596
15597
15598 #if !defined(DACCESS_COMPILE) && defined(FEATURE_CER)
15599
15600 // Access to CerPrepInfo, the structure used to track CERs prepared at runtime (as opposed to ngen time). GetCerPrepInfo will
15601 // return the structure associated with the given method desc if it exists or NULL otherwise. CreateCerPrepInfo will get the
15602 // structure if it exists or allocate and return a new struct otherwise. Creation of CerPrepInfo structures is automatically
15603 // synchronized by the CerCrst (lazily allocated as needed).
15604 CerPrepInfo *Module::GetCerPrepInfo(MethodDesc *pMD)
15605 {
15606     CONTRACTL
15607     {
15608         NOTHROW;
15609         GC_NOTRIGGER;
15610         MODE_ANY;
15611         SO_TOLERANT;
15612         PRECONDITION(CheckPointer(pMD));
15613     }
15614     CONTRACTL_END;
15615
15616     if (m_pCerPrepInfo == NULL)
15617         return NULL;
15618
15619     // Don't need a crst for read only access to the hash table.
15620     HashDatum sDatum;
15621     if (m_pCerPrepInfo->GetValue(pMD, &sDatum))
15622         return (CerPrepInfo*)sDatum;
15623     else
15624         return NULL;
15625 }
15626
15627 CerPrepInfo *Module::CreateCerPrepInfo(MethodDesc *pMD)
15628 {
15629     CONTRACTL
15630     {
15631         THROWS;
15632         GC_TRIGGERS;
15633         MODE_ANY;
15634         PRECONDITION(CheckPointer(pMD));
15635     }
15636     CONTRACTL_END;
15637
15638     // Lazily allocate a Crst to serialize update access to the info structure.
15639     // Carefully synchronize to ensure we don't leak a Crst in race conditions.
15640     if (m_pCerCrst == NULL)
15641     {
15642         Crst *pCrst = new Crst(CrstCer);
15643         if (InterlockedCompareExchangeT(&m_pCerCrst, pCrst, NULL) != NULL)
15644             delete pCrst;
15645     }
15646
15647     CrstHolder sCrstHolder(m_pCerCrst);
15648
15649     // Lazily allocate the info structure.
15650     if (m_pCerPrepInfo == NULL)
15651     {
15652         LockOwner sLock = {m_pCerCrst, IsOwnerOfCrst};
15653         NewHolder <EEPtrHashTable> tempCerPrepInfo (new EEPtrHashTable());
15654         if (!tempCerPrepInfo->Init(CER_DEFAULT_HASH_SIZE, &sLock))
15655             COMPlusThrowOM();
15656         m_pCerPrepInfo = tempCerPrepInfo.Extract ();
15657     }
15658     else
15659     {
15660         // Try getting an existing value first.
15661         HashDatum sDatum;
15662         if (m_pCerPrepInfo->GetValue(pMD, &sDatum))
15663             return (CerPrepInfo*)sDatum;
15664     }
15665
15666     // We get here if there was no info structure or no existing method desc entry. Either way we now have an info structure and
15667     // need to create a new method desc entry.
15668     NewHolder<CerPrepInfo> pInfo(new CerPrepInfo());
15669
15670     m_pCerPrepInfo->InsertValue(pMD, (HashDatum)pInfo);
15671
15672     return pInfo.Extract();
15673 }
15674
15675 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
15676 // Access to CerNgenRootTable which holds holds information for all the CERs rooted at a method in this module (that were
15677 // discovered during an ngen).
15678
15679 // Add a list of MethodContextElements representing a CER to the root table keyed by the MethodDesc* of the root method. Creates
15680 // or expands the root table as necessary. This should only be called during ngen (at runtime we only read the table).
15681 void Module::AddCerListToRootTable(MethodDesc *pRootMD, MethodContextElement *pList)
15682 {
15683     CONTRACTL
15684     {
15685         STANDARD_VM_CHECK;
15686         PRECONDITION(IsCompilationProcess());
15687     }
15688     CONTRACTL_END;
15689
15690     // Although this is only called during ngen we still get cases where a module comes through here already ngen'd (because of
15691     // ngen's habit of letting code execute during compilation). Until that's fixed we'll just back out if the module has already
15692     // fixed the root table into unwriteable storage.
15693     if (m_pCerNgenRootTable && !(m_dwTransientFlags & M_CER_ROOT_TABLE_ON_HEAP))
15694         return;
15695
15696     // Lazily allocate a Crst to serialize update access to the info structure.
15697     // Carefully synchronize to ensure we don't leak a Crst in race conditions.
15698     if (m_pCerCrst == NULL)
15699     {
15700         Crst *pCrst = new Crst(CrstCer);
15701         if (InterlockedCompareExchangeT(&m_pCerCrst, pCrst, NULL) != NULL)
15702             delete pCrst;
15703     }
15704
15705     CrstHolder sCrstHolder(m_pCerCrst);
15706
15707     // Lazily allocate the root table structure.
15708     if (m_pCerNgenRootTable == NULL)
15709     {
15710         FastInterlockOr(&m_dwTransientFlags, M_CER_ROOT_TABLE_ON_HEAP);
15711         m_pCerNgenRootTable = new CerNgenRootTable();
15712     }
15713
15714     _ASSERTE(m_dwTransientFlags & M_CER_ROOT_TABLE_ON_HEAP);
15715
15716     // And add the new element.
15717     m_pCerNgenRootTable->AddRoot(pRootMD, pList);
15718 }
15719 #endif // FEATURE_NATIVE_IMAGE_GENERATION
15720
15721 #ifdef FEATURE_PREJIT 
15722 // Returns true if the given method is a CER root detected at ngen time.
15723 bool Module::IsNgenCerRootMethod(MethodDesc *pMD)
15724 {
15725     CONTRACTL
15726     {
15727         NOTHROW;
15728         GC_NOTRIGGER;
15729         SO_TOLERANT;
15730         MODE_ANY;
15731     }
15732     CONTRACTL_END;
15733     _ASSERTE(pMD->GetModule() == this);
15734     if (m_pCerNgenRootTable)
15735         return m_pCerNgenRootTable->IsNgenRootMethod(pMD);
15736     return false;
15737 }
15738
15739 // Restores the CER rooted at this method (no-op if this method isn't a CER root).
15740 void Module::RestoreCer(MethodDesc *pMD)
15741 {
15742     STANDARD_VM_CONTRACT;
15743     _ASSERTE(pMD->GetModule() == this);
15744     if (m_pCerNgenRootTable)
15745         m_pCerNgenRootTable->Restore(pMD);
15746 }
15747
15748 #endif // FEATURE_PREJIT
15749
15750 #endif // !DACCESS_COMPILE && FEATURE_CER
15751
15752
15753
15754 //-------------------------------------------------------------------------------
15755 // Make best-case effort to obtain an image name for use in an error message.
15756 //
15757 // This routine must expect to be called before the this object is fully loaded.
15758 // It can return an empty if the name isn't available or the object isn't initialized
15759 // enough to get a name, but it mustn't crash.
15760 //-------------------------------------------------------------------------------
15761 LPCWSTR Module::GetPathForErrorMessages()
15762 {
15763     CONTRACTL
15764     {
15765         THROWS;
15766         GC_TRIGGERS;
15767         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
15768     }
15769     CONTRACTL_END
15770
15771     PEFile *pFile = GetFile();
15772     
15773     if (pFile)
15774     {
15775         return pFile->GetPathForErrorMessages();
15776     }
15777     else
15778     {
15779         return W("");
15780     }
15781 }
15782
15783 #ifndef DACCESS_COMPILE
15784 BOOL IsVerifiableWrapper(MethodDesc* pMD)
15785 {
15786     BOOL ret = FALSE;
15787     //EX_TRY contains _alloca, so I can't use this inside of a loop.  4wesome.
15788     EX_TRY
15789     {
15790         ret = pMD->IsVerifiable();
15791     }
15792     EX_CATCH
15793     {
15794         //if the method has a security exception, it will fly through IsVerifiable.  Shunt
15795         //to the unverifiable path below.
15796     }
15797     EX_END_CATCH(RethrowTerminalExceptions)
15798     return ret;
15799 }
15800 #endif //DACCESS_COMPILE
15801 void Module::VerifyAllMethods()
15802 {
15803     CONTRACTL
15804     {
15805         THROWS;
15806         GC_TRIGGERS;
15807         MODE_ANY;
15808     }
15809     CONTRACTL_END;
15810 #ifndef DACCESS_COMPILE
15811     //If the EE isn't started yet, it's not safe to jit.  We fail in COM jitting a p/invoke.
15812     if (!g_fEEStarted)
15813         return;
15814
15815     struct Local
15816     {
15817         static bool VerifyMethodsForTypeDef(Module * pModule, mdTypeDef td)
15818         {
15819             bool ret = true;
15820             TypeHandle th = ClassLoader::LoadTypeDefThrowing(pModule, td, ClassLoader::ThrowIfNotFound,
15821                                                              ClassLoader::PermitUninstDefOrRef);
15822
15823             MethodTable * pMT = th.GetMethodTable();
15824             MethodTable::MethodIterator it(pMT);
15825             for (; it.IsValid(); it.Next())
15826             {
15827                 MethodDesc * pMD = it.GetMethodDesc();
15828                 if (pMD->HasILHeader() && Security::IsMethodTransparent(pMD)
15829                     && (g_pObjectCtorMD != pMD))
15830                 {
15831                     if (!IsVerifiableWrapper(pMD))
15832                     {
15833 #ifdef _DEBUG
15834                         SString s;
15835                         if (LoggingOn(LF_VERIFIER, LL_ERROR))
15836                             TypeString::AppendMethodDebug(s, pMD);
15837                         LOG((LF_VERIFIER, LL_ERROR, "Transparent Method (0x%p), %S is unverifiable\n",
15838                              pMD, s.GetUnicode()));
15839 #endif
15840                         ret = false;
15841                     }
15842                 }
15843             }
15844             return ret;
15845         }
15846     };
15847     //Verify all methods in a module eagerly, forcing them to get loaded.
15848
15849     /* XXX Thu 4/26/2007
15850      * This code is lifted mostly from Validator.cpp
15851      */
15852     IMDInternalImport * pMDI = GetMDImport();
15853     HENUMTypeDefInternalHolder hEnum(pMDI);
15854     mdTypeDef td;
15855     hEnum.EnumTypeDefInit();
15856
15857     bool isAllVerifiable = true;
15858     //verify global methods
15859     if (GetGlobalMethodTable())
15860     {
15861         //verify everything in the MT.
15862         if (!Local::VerifyMethodsForTypeDef(this, COR_GLOBAL_PARENT_TOKEN))
15863             isAllVerifiable = false;
15864     }
15865     while (pMDI->EnumTypeDefNext(&hEnum, &td))
15866     {
15867         //verify everything
15868         if (!Local::VerifyMethodsForTypeDef(this, td))
15869             isAllVerifiable = false;
15870     }
15871     if (!isAllVerifiable)
15872         EEFileLoadException::Throw(GetFile(), COR_E_VERIFICATION);
15873 #endif //DACCESS_COMPILE
15874 }
15875
15876
15877 #if defined(_DEBUG) && !defined(DACCESS_COMPILE) && !defined(CROSS_COMPILE)
15878 void Module::ExpandAll()
15879 {
15880     CONTRACTL
15881     {
15882         THROWS;
15883         GC_TRIGGERS;
15884         MODE_ANY;
15885     }
15886     CONTRACTL_END;
15887
15888     //This is called from inside EEStartupHelper, so it breaks the SO rules.  However, this is debug only
15889     //(and only supported for limited jit testing), so it's ok here.
15890     CONTRACT_VIOLATION(SOToleranceViolation);
15891
15892     //If the EE isn't started yet, it's not safe to jit.  We fail in COM jitting a p/invoke.
15893     if (!g_fEEStarted)
15894         return;
15895     struct Local
15896     {
15897         static void CompileMethodDesc(MethodDesc * pMD)
15898         {
15899             //Must have a method body
15900             if (pMD->HasILHeader()
15901                 //Can't jit open instantiations
15902                 && !pMD->IsGenericMethodDefinition()
15903                 //These are the only methods we can jit
15904                 && (pMD->IsStatic() || pMD->GetNumGenericMethodArgs() == 0
15905                     || pMD->HasClassInstantiation())
15906                 && (pMD->MayHaveNativeCode() && !pMD->IsFCallOrIntrinsic()))
15907             {
15908                 COR_ILMETHOD * ilHeader = pMD->GetILHeader();
15909                 COR_ILMETHOD_DECODER::DecoderStatus ignored;
15910                 NewHolder<COR_ILMETHOD_DECODER> pHeader(new COR_ILMETHOD_DECODER(ilHeader,
15911                                                                                  pMD->GetMDImport(),
15912                                                                                  &ignored));
15913 #ifdef FEATURE_INTERPRETER
15914                 pMD->MakeJitWorker(pHeader, CORJIT_FLAGS(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE));
15915 #else
15916                 pMD->MakeJitWorker(pHeader, CORJIT_FLAGS());
15917 #endif
15918             }
15919         }
15920         static void CompileMethodsForMethodTable(MethodTable * pMT)
15921         {
15922             MethodTable::MethodIterator it(pMT);
15923             for (; it.IsValid(); it.Next())
15924             {
15925                 MethodDesc * pMD = it.GetMethodDesc();
15926                 CompileMethodDesc(pMD);
15927             }
15928         }
15929 #if 0
15930         static void CompileMethodsForTypeDef(Module * pModule, mdTypeDef td)
15931         {
15932             TypeHandle th = ClassLoader::LoadTypeDefThrowing(pModule, td, ClassLoader::ThrowIfNotFound,
15933                                                              ClassLoader::PermitUninstDefOrRef);
15934
15935             MethodTable * pMT = th.GetMethodTable();
15936             CompileMethodsForMethodTable(pMT);
15937         }
15938 #endif
15939         static void CompileMethodsForTypeDefRefSpec(Module * pModule, mdToken tok)
15940         {
15941             TypeHandle th;
15942             HRESULT hr = S_OK;
15943
15944             EX_TRY
15945             {
15946                 th = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
15947                     pModule, 
15948                     tok, 
15949                     NULL /*SigTypeContext*/);
15950             }
15951             EX_CATCH
15952             {
15953                 hr = GET_EXCEPTION()->GetHR();
15954             }
15955             EX_END_CATCH(SwallowAllExceptions);
15956
15957             //Only do this for non-generic types and unshared generic types
15958             //(canonical generics and value type generic instantiations).
15959             if (SUCCEEDED(hr) && !th.IsTypeDesc()
15960                             && th.AsMethodTable()->IsCanonicalMethodTable())
15961             {
15962                 CompileMethodsForMethodTable(th.AsMethodTable());
15963             }
15964         }
15965         static void CompileMethodsForMethodDefRefSpec(Module * pModule, mdToken tok)
15966         {
15967             HRESULT hr = S_OK;
15968             EX_TRY
15969             {
15970                 MethodDesc * pMD =
15971                     MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(pModule, tok,
15972                                                                         /*SigTypeContext*/NULL,
15973                                                                         TRUE, TRUE);
15974                 CompileMethodDesc(pMD);
15975             }
15976             EX_CATCH
15977             {
15978                 hr = GET_EXCEPTION()->GetHR();
15979                 //@telesto what should we do with this HR?  the Silverlight code doesn't seem
15980                 //to do anything...but that doesn't seem safe...
15981             }
15982             EX_END_CATCH(SwallowAllExceptions);
15983         }
15984     };
15985     //Jit all methods eagerly
15986
15987     /* XXX Thu 4/26/2007
15988      * This code is lifted mostly from code:Module::VerifyAllMethods
15989      */
15990     IMDInternalImport * pMDI = GetMDImport();
15991     HENUMTypeDefInternalHolder hEnum(pMDI);
15992     mdTypeDef td;
15993     hEnum.EnumTypeDefInit();
15994
15995     //verify global methods
15996     if (GetGlobalMethodTable())
15997     {
15998         //jit everything in the MT.
15999         Local::CompileMethodsForTypeDefRefSpec(this, COR_GLOBAL_PARENT_TOKEN);
16000     }
16001     while (pMDI->EnumTypeDefNext(&hEnum, &td))
16002     {
16003         //jit everything
16004         Local::CompileMethodsForTypeDefRefSpec(this, td);
16005     }
16006
16007     //Get the type refs.  They're always awesome.
16008     HENUMInternalHolder hEnumTypeRefs(pMDI);
16009     mdToken tr;
16010
16011     hEnumTypeRefs.EnumAllInit(mdtTypeRef);
16012     while (hEnumTypeRefs.EnumNext(&tr))
16013     {
16014         Local::CompileMethodsForTypeDefRefSpec(this, tr);
16015     }
16016
16017     //make sure to get the type specs
16018     HENUMInternalHolder hEnumTypeSpecs(pMDI);
16019     mdToken ts;
16020
16021     hEnumTypeSpecs.EnumAllInit(mdtTypeSpec);
16022     while (hEnumTypeSpecs.EnumNext(&ts))
16023     {
16024         Local::CompileMethodsForTypeDefRefSpec(this, ts);
16025     }
16026
16027
16028     //And now for the interesting generic methods
16029     HENUMInternalHolder hEnumMethodSpecs(pMDI);
16030     mdToken ms;
16031
16032     hEnumMethodSpecs.EnumAllInit(mdtMethodSpec);
16033     while (hEnumMethodSpecs.EnumNext(&ms))
16034     {
16035         Local::CompileMethodsForMethodDefRefSpec(this, ms);
16036     }
16037 }
16038 #endif //_DEBUG && !DACCESS_COMPILE && !CROSS_COMPILE
16039
16040 //-------------------------------------------------------------------------------
16041
16042 // Verify consistency of asmconstants.h
16043
16044 // Wrap all C_ASSERT's in asmconstants.h with a class definition.  Many of the
16045 // fields referenced below are private, and this class is a friend of the
16046 // enclosing type.  (A C_ASSERT isn't a compiler intrinsic, just a magic
16047 // typedef that produces a compiler error when the condition is false.)
16048 #include "clrvarargs.h" /* for VARARG C_ASSERTs in asmconstants.h */
16049 class CheckAsmOffsets
16050 {
16051 #define ASMCONSTANTS_C_ASSERT(cond) \
16052         typedef char UNIQUE_LABEL(__C_ASSERT__)[(cond) ? 1 : -1];
16053 #include "asmconstants.h"
16054 };
16055
16056 //-------------------------------------------------------------------------------
16057
16058 #ifndef DACCESS_COMPILE
16059
16060 void Module::CreateAssemblyRefByNameTable(AllocMemTracker *pamTracker)
16061 {
16062     CONTRACTL
16063     {
16064         THROWS;
16065         GC_NOTRIGGER;
16066         INJECT_FAULT(COMPlusThrowOM(););
16067     }
16068     CONTRACTL_END
16069
16070     LoaderHeap *        pHeap       = GetLoaderAllocator()->GetLowFrequencyHeap();
16071     IMDInternalImport * pImport     = GetMDImport();
16072
16073     DWORD               dwMaxRid    = pImport->GetCountWithTokenKind(mdtAssemblyRef);
16074     if (dwMaxRid == 0)
16075         return;
16076
16077     S_SIZE_T            dwAllocSize = S_SIZE_T(sizeof(LPWSTR)) * S_SIZE_T(dwMaxRid);
16078     m_AssemblyRefByNameTable = (LPCSTR *) pamTracker->Track( pHeap->AllocMem(dwAllocSize) );
16079
16080     DWORD dwCount = 0;
16081     for (DWORD rid=1; rid <= dwMaxRid; rid++)
16082     {
16083         mdAssemblyRef mdToken = TokenFromRid(rid,mdtAssemblyRef);
16084         LPCSTR        szName;
16085         HRESULT       hr;
16086
16087         hr = pImport->GetAssemblyRefProps(mdToken, NULL, NULL, &szName, NULL, NULL, NULL, NULL);
16088
16089         if (SUCCEEDED(hr))
16090         {
16091             m_AssemblyRefByNameTable[dwCount++] = szName;
16092         }
16093     }
16094     m_AssemblyRefByNameCount = dwCount;
16095 }
16096
16097 bool Module::HasReferenceByName(LPCUTF8 pModuleName)
16098 {
16099     LIMITED_METHOD_CONTRACT;
16100
16101     for (DWORD i=0; i < m_AssemblyRefByNameCount; i++)
16102     {
16103         if (0 == strcmp(pModuleName, m_AssemblyRefByNameTable[i]))
16104             return true;
16105     }
16106
16107     return false;
16108 }
16109 #endif
16110
16111 #ifdef _MSC_VER
16112 #pragma warning(pop)
16113 #endif // _MSC_VER: warning C4244
16114
16115 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
16116 NOINLINE void NgenForceFailure_AV()
16117 {
16118     LIMITED_METHOD_CONTRACT;
16119     static int* alwaysNull = 0;
16120     *alwaysNull = 0;
16121 }
16122
16123 NOINLINE void NgenForceFailure_TypeLoadException()
16124 {
16125     WRAPPER_NO_CONTRACT;
16126     ::ThrowTypeLoadException("ForceIBC", "Failure", W("Assembly"), NULL, IDS_CLASSLOAD_BADFORMAT);       
16127 }
16128
16129 void EEConfig::DebugCheckAndForceIBCFailure(BitForMask bitForMask)
16130 {
16131     CONTRACTL
16132     {
16133         THROWS;
16134         GC_NOTRIGGER;
16135         MODE_ANY;
16136     }
16137     CONTRACTL_END;
16138     static DWORD s_ibcCheckCount = 0;
16139
16140     // Both of these must be set to non-zero values for us to force a failure
16141     // 
16142     if ((NgenForceFailureCount() == 0) || (NgenForceFailureKind() == 0))
16143         return;
16144
16145     // The bitForMask value must also beset in the FailureMask
16146     // 
16147     if ((((DWORD) bitForMask) & NgenForceFailureMask()) == 0)
16148         return;
16149
16150     s_ibcCheckCount++;
16151     if (s_ibcCheckCount < NgenForceFailureCount())
16152         return;
16153
16154     // We force one failure every NgenForceFailureCount()
16155     // 
16156     s_ibcCheckCount = 0;
16157     switch (NgenForceFailureKind())
16158     {
16159     case 1:
16160         NgenForceFailure_TypeLoadException();
16161         break;
16162     case 2:
16163         NgenForceFailure_AV();
16164         break;
16165     }
16166 }
16167 #endif // defined(_DEBUG) && !defined(DACCESS_COMPILE)
16168