Merge pull request #2192 from dasMulli/random-seeding-improvements
[platform/upstream/coreclr.git] / src / vm / compile.h
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: compile.h
6 //
7 // Interfaces and support for zap compiler and zap files
8 // 
9
10 // ===========================================================================
11
12
13 /*
14
15 The preloader is used to serialize internal EE data structures in the
16 zapped image.  The object model looks like the following:
17
18                     +--------------------+
19                     |                    |
20                     |    ZapperModule    |
21                     |                    |
22                     +--------------------+
23                               |
24                               *    
25                      ICorCompileDataStore           Zapper
26                     
27            =====================================================      
28                     
29                      ICorCompilePreloader           EE
30                               * 
31                               | 
32                     +--------------------+
33                     |                    |
34                     |    CEEPreloader    |
35                     |                    |
36                     +--------------------+                    
37                               |
38                               *    
39                      DataImage::IDataStore                    
40                     
41                                                  
42                     +--------------------+
43                     |                    |
44                     |     DataImage      |
45                     |                    |
46                     +--------------------+
47                     
48 ZapperModule - Created by the zapper for each module.  It implements the
49                ICorCompileDataStore interface that the preloader uses to
50                allocate space for the EE data structures.  Currently it
51                allocates space in a single PE section (though the DataImage
52                has logic to further subdivide the space into subsections).
53   
54 CEEPreloader - Created by ZapperModule in order to serialize EE
55                data structures.  It implements two interfaces.  
56                ICorCompilePreloader is used by ZapperModule to inquire
57                about the offsets of various EE data structures inside
58                the preloader section.  DataImage::IDataStore is used
59                by DataImage to manage the PE section memory, and the
60                implementation in the CEEPreloader mostly forwards the calls
61                to the zapper (ICorCompileDataStore).
62
63 DataImage    - Created by CEEPreloader to keep track of memory used by
64                EE data structures.  Even though it uses only one PE
65                section, it allows the EE to allocate memory in multiple
66                subsections.  This is accomplished by splitting the work into
67                three phases (there are comments in dataimage.h that explain
68                this in detail).
69                
70
71 The CEEPreloader is created when ZapperModule::Preload calls
72 m_zapper->m_pEECompileInfo->PreloadModule.  PreloadModule creates
73 the CEEPreloader and then calls its Preload method, which explicitely
74 loads all the EE objects into memory (Module::ExpandAll), and then
75 allocates space for them in the preloader section (Module::Save).
76
77 Each EE data structure that needs to be serialized implements a Save
78 method.  A Save method is required to:
79 1) Store all of its data (including strings and other buffers that it
80    uses) in the preloader section.  This is accomplished by calling on
81    one of the DataImage storage methods (such as DataImage::StoreStructure).
82 2) Call the Save method on the objects that it owns.  The interesting
83    part of the hierarchy looks like:
84    
85    Module::Save
86      MethodTable::Save (in profile order)
87        EEClass::Save
88          MethodDescChunk::Save (method desc chunks can be split into hot 
89                                 and cold based on profile info)
90            MethodDesc::Save
91            
92 Note that while the architecture requires the data structures in the
93 preloader sections to look like their EE counterparts, it is possible
94 to work around that limitation by constructing multiple submappings of
95 these data structures.  Sometimes the submappings require a change to the actual
96 data (i.e. each method desc has information that tells you how far it is
97 from the MethodDescChunk, and that needs to change when reordering method
98 descs).  In such cases you create new copies of that memory and construct
99 a regular copying map for each of the new updated copies (DataImage::StoreStructure),
100 and a pointer update map for each of the original EE data structures 
101 (DataImage::StoreStructureUsingSurrogate).  See MethodDescChunk::Save for
102 an example on how to do this.
103
104 Fixups:  once everything has been layout out in memory, the ZapperModule
105 calls CEEPreloader::Link to generate fixups for the data.  CEEPreloader::Link
106 calls Module::Fixup, which results in a data structure walk very similar to
107 that of Module::Save.  Each data structure calls one of the FixupPointerField
108 methods on the DataImage, which in turn forwards the call to
109 CEEPreloader::AddFixup, which forwards it to the zapper 
110 (ZapperModule::AddFixup).
111    
112 */
113
114 #ifndef COMPILE_H_
115 #define COMPILE_H_
116
117 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
118
119 struct ZapperLoaderModuleTableKey {
120     ZapperLoaderModuleTableKey(Module *pDefinitionModule, 
121         mdToken token, 
122         Instantiation classInst,
123         Instantiation methodInst)
124         : m_inst(classInst, methodInst)
125     { WRAPPER_NO_CONTRACT;
126       this->m_pDefinitionModule = pDefinitionModule;
127       this->m_token = token;  }
128     
129     Module *m_pDefinitionModule;
130     mdToken m_token;
131     SigTypeContext m_inst;
132 } ;
133
134 struct ZapperLoaderModuleTableEntry {
135     ZapperLoaderModuleTableEntry(): key(0,0,Instantiation(),Instantiation()) { WRAPPER_NO_CONTRACT; this->result = 0; }
136     ZapperLoaderModuleTableEntry(const ZapperLoaderModuleTableKey &_key,Module *_result) 
137         : key(_key)
138     { this->result = _result; }
139     
140     ZapperLoaderModuleTableKey key;
141     Module *result;
142 } ;
143
144 class ZapperLoaderModuleTableTraits : public NoRemoveSHashTraits<DefaultSHashTraits<ZapperLoaderModuleTableEntry> >
145 {
146     
147 public:
148     typedef const ZapperLoaderModuleTableKey *key_t;
149     static const ZapperLoaderModuleTableKey * GetKey(const ZapperLoaderModuleTableEntry &e) { return &e.key; }
150     static count_t Hash(const ZapperLoaderModuleTableKey * k) 
151     { 
152         LIMITED_METHOD_CONTRACT;
153         
154         DWORD dwHash = 5381;
155         
156         dwHash = ((dwHash << 5) + dwHash) ^ (unsigned int)(SIZE_T)k->m_pDefinitionModule;
157         dwHash = ((dwHash << 5) + dwHash) ^ (unsigned int)(SIZE_T)k->m_token;
158         dwHash = ((dwHash << 5) + dwHash) ^ EEInstantiationHashTableHelper:: Hash(&k->m_inst);
159         return dwHash;
160     }
161     
162     static BOOL Equals(const ZapperLoaderModuleTableKey *e1, const ZapperLoaderModuleTableKey *e2)
163     {
164         WRAPPER_NO_CONTRACT;
165         return e1->m_pDefinitionModule == e2->m_pDefinitionModule && 
166             e1->m_token == e2->m_token && 
167             SigTypeContext::Equal(&e1->m_inst, &e2->m_inst);
168     }
169     static const ZapperLoaderModuleTableEntry Null() 
170     { return ZapperLoaderModuleTableEntry(); }
171     
172     static bool IsNull(const ZapperLoaderModuleTableEntry &e) 
173     { LIMITED_METHOD_CONTRACT; return e.key.m_pDefinitionModule == 0 && e.key.m_token == 0 && e.key.m_inst.IsEmpty(); }
174     
175 };
176
177
178 typedef  SHash<ZapperLoaderModuleTableTraits> ZapperLoaderModuleTable;
179
180 class CEECompileInfo : public ICorCompileInfo
181 {
182   public:
183     virtual ~CEECompileInfo()
184     {
185         WRAPPER_NO_CONTRACT;
186     }
187     
188     HRESULT Startup(     BOOL                     fForceDebug, 
189                          BOOL                     fForceProfiling,
190                          BOOL                     fForceInstrument);
191
192     HRESULT CreateDomain(ICorCompilationDomain **ppDomain,
193                          IMetaDataAssemblyEmit    *pEmitter,
194                          BOOL                     fForceDebug,
195                          BOOL                     fForceProfiling,
196                          BOOL                     fForceInstrument,
197                          BOOL                     fForceFulltrustDomain);
198
199     HRESULT MakeCrossDomainCallback(
200                                     ICorCompilationDomain*  pDomain,
201                                     CROSS_DOMAIN_CALLBACK   pfnCallback,
202                                     LPVOID                  pArgs);
203    
204     HRESULT DestroyDomain(ICorCompilationDomain   *pDomain);
205
206     HRESULT LoadAssemblyByPath(LPCWSTR                  wzPath,
207                                BOOL                     fExplicitBindToNativeImage,
208                                CORINFO_ASSEMBLY_HANDLE *pHandle);
209
210 #ifdef FEATURE_FUSION
211     HRESULT LoadAssemblyByName(LPCWSTR                  wzName,
212                                CORINFO_ASSEMBLY_HANDLE *pHandle);
213
214     HRESULT LoadAssemblyRef(IMDInternalImport     *pAssemblyImport,
215                             mdAssemblyRef           ref,
216                             CORINFO_ASSEMBLY_HANDLE *pHandle,
217                             IAssemblyName           **refAssemblyName = NULL);
218
219     HRESULT LoadAssemblyByIAssemblyName(
220             IAssemblyName           *pAssemblyName,
221             CORINFO_ASSEMBLY_HANDLE *pHandle
222             );
223
224 #endif //FEATURE_FUSION
225
226 #ifdef FEATURE_COMINTEROP
227     HRESULT LoadTypeRefWinRT(IMDInternalImport       *pAssemblyImport,
228                                      mdTypeRef               ref,
229                                      CORINFO_ASSEMBLY_HANDLE *pHandle);
230 #endif
231
232     BOOL IsInCurrentVersionBubble(CORINFO_MODULE_HANDLE hModule);
233
234     HRESULT LoadAssemblyModule(CORINFO_ASSEMBLY_HANDLE assembly,
235                                mdFile                  file,
236                                CORINFO_MODULE_HANDLE   *pHandle);
237
238 #ifndef FEATURE_CORECLR
239     // Check if the assembly supports automatic NGen
240     BOOL SupportsAutoNGen(CORINFO_ASSEMBLY_HANDLE assembly);
241
242     HRESULT SetCachedSigningLevel(HANDLE hNI, HANDLE *pModules, COUNT_T nModules);
243 #endif
244
245     BOOL CheckAssemblyZap(
246         CORINFO_ASSEMBLY_HANDLE assembly, 
247       __out_ecount_opt(*cAssemblyManifestModulePath) 
248         LPWSTR                  assemblyManifestModulePath, 
249         LPDWORD                 cAssemblyManifestModulePath);
250
251     HRESULT SetCompilationTarget(CORINFO_ASSEMBLY_HANDLE     assembly,
252                                  CORINFO_MODULE_HANDLE       module);
253
254     IMDInternalImport * GetAssemblyMetaDataImport(CORINFO_ASSEMBLY_HANDLE scope);
255
256     IMDInternalImport * GetModuleMetaDataImport(CORINFO_MODULE_HANDLE scope);
257
258     CORINFO_MODULE_HANDLE GetAssemblyModule(CORINFO_ASSEMBLY_HANDLE module);
259
260     CORINFO_ASSEMBLY_HANDLE GetModuleAssembly(CORINFO_MODULE_HANDLE module);
261
262     PEDecoder * GetModuleDecoder(CORINFO_MODULE_HANDLE scope);
263
264     void GetModuleFileName(CORINFO_MODULE_HANDLE module,
265                            SString               &result);
266
267     void EncodeModuleAsIndexes( CORINFO_MODULE_HANDLE   fromHandle,
268                                 CORINFO_MODULE_HANDLE   handle,
269                                 DWORD                   *pAssemblyIndex,
270                                 DWORD                   *pModuleIndex,
271                                 IMetaDataAssemblyEmit   *pAssemblyEmit); 
272
273     void EncodeClass(  CORINFO_MODULE_HANDLE   referencingModule,
274                        CORINFO_CLASS_HANDLE    classHandle,
275                        SigBuilder              *pSigBuilder,
276                        LPVOID                  encodeContext,
277                        ENCODEMODULE_CALLBACK   pfnEncodeModule);
278
279     void EncodeMethod( CORINFO_MODULE_HANDLE   referencingModule,
280                        CORINFO_METHOD_HANDLE   methHnd,
281                        SigBuilder              *pSigBuilder,
282                        LPVOID                  encodeContext,
283                        ENCODEMODULE_CALLBACK   pfnEncodeModule,
284                        CORINFO_RESOLVED_TOKEN  *pResolvedToken,
285                        CORINFO_RESOLVED_TOKEN  *pConstrainedResolvedToken,
286                        BOOL                    fEncodeUsingResolvedTokenSpecStreams);
287
288     virtual mdToken TryEncodeMethodAsToken(CORINFO_METHOD_HANDLE handle, 
289                                            CORINFO_RESOLVED_TOKEN * pResolvedToken,
290                                            CORINFO_MODULE_HANDLE * referencingModule);
291
292     virtual DWORD TryEncodeMethodSlot(CORINFO_METHOD_HANDLE handle);
293
294     void EncodeField(  CORINFO_MODULE_HANDLE   referencingModule,
295                        CORINFO_FIELD_HANDLE    handle,
296                        SigBuilder              *pSigBuilder,
297                        LPVOID                  encodeContext,
298                        ENCODEMODULE_CALLBACK   pfnEncodeModule,
299                        CORINFO_RESOLVED_TOKEN  *pResolvedToken,
300                        BOOL                    fEncodeUsingResolvedTokenSpecStreams);
301
302     // Encode generic dictionary signature
303     virtual void EncodeGenericSignature(
304             LPVOID signature,
305             BOOL fMethod,
306             SigBuilder * pSigBuilder,
307             LPVOID encodeContext,
308             ENCODEMODULE_CALLBACK pfnEncodeModule);
309
310
311     BOOL IsEmptyString(mdString token,
312                        CORINFO_MODULE_HANDLE module);
313
314     BOOL IsNativeCallableMethod(CORINFO_METHOD_HANDLE handle);
315
316     BOOL IsCachingOfInliningHintsEnabled()
317     {
318         return m_fCachingOfInliningHintsEnabled;
319     }
320
321     void DisableCachingOfInliningHints()
322     {
323         m_fCachingOfInliningHintsEnabled = FALSE;
324     }
325
326     HRESULT GetTypeDef(   CORINFO_CLASS_HANDLE    classHandle,
327                           mdTypeDef               *token);
328     HRESULT GetMethodDef( CORINFO_METHOD_HANDLE   methodHandle,
329                           mdMethodDef             *token);
330     HRESULT GetFieldDef(  CORINFO_FIELD_HANDLE    fieldHandle,
331                           mdFieldDef              *token);
332
333     void SetAssemblyHardBindList(__in_ecount( cHardBindList )
334                                  LPWSTR *pHardBindList,
335                                  DWORD cHardBindList);
336
337     CORINFO_MODULE_HANDLE GetLoaderModuleForMscorlib();
338     CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableType(CORINFO_CLASS_HANDLE classHandle);
339     CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableMethod(CORINFO_METHOD_HANDLE methodHandle);
340     CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableField(CORINFO_FIELD_HANDLE fieldHandle);
341
342     ICorCompilePreloader * PreloadModule(CORINFO_MODULE_HANDLE   moduleHandle,
343                                     ICorCompileDataStore    *pData,
344                                     CorProfileData          *profileData);
345
346 #ifdef FEATURE_FUSION
347     HRESULT GetAssemblyName(
348             CORINFO_ASSEMBLY_HANDLE hAssembly,
349             DWORD                   dwFlags,
350             __out_z LPWSTR          wzAssemblyName, 
351             LPDWORD                 cchAssemblyName);
352 #endif //FEATURE_FUSION
353     
354     HRESULT GetLoadHint(CORINFO_ASSEMBLY_HANDLE   hAssembly,
355                         CORINFO_ASSEMBLY_HANDLE hAssemblyDependency,
356                         LoadHintEnum           *loadHint,
357                         LoadHintEnum           *defaultLoadHint);
358
359     HRESULT GetAssemblyVersionInfo(CORINFO_ASSEMBLY_HANDLE Handle, 
360                                     CORCOMPILE_VERSION_INFO *pInfo);
361
362     void GetAssemblyCodeBase(CORINFO_ASSEMBLY_HANDLE hAssembly,
363                              SString                &result);
364
365     void GetCallRefMap(CORINFO_METHOD_HANDLE hMethod, 
366                        GCRefMapBuilder * pBuilder);
367
368     void CompressDebugInfo(
369                                     IN ICorDebugInfo::OffsetMapping * pOffsetMapping,
370                                     IN ULONG            iOffsetMapping,
371                                     IN ICorDebugInfo::NativeVarInfo * pNativeVarInfo,
372                                     IN ULONG            iNativeVarInfo,
373                                     IN OUT SBuffer    * pDebugInfoBuffer);
374
375     HRESULT SetVerboseLevel(
376                                     IN  VerboseLevel        level);
377
378     HRESULT GetBaseJitFlags(
379             IN  CORINFO_METHOD_HANDLE    hMethod,
380             OUT DWORD                   *pFlags);
381
382 #ifdef _WIN64
383     SIZE_T  getPersonalityValue();
384 #endif
385
386     void* GetStubSize(void *pStubAddress, DWORD *pSizeToCopy);
387
388     HRESULT GetStubClone(void *pStub, BYTE *pBuffer, DWORD dwBufferSize);
389
390     BOOL GetIsGeneratingNgenPDB();
391     void SetIsGeneratingNgenPDB(BOOL fGeneratingNgenPDB);
392
393 #ifdef FEATURE_READYTORUN_COMPILER
394     CORCOMPILE_FIXUP_BLOB_KIND GetFieldBaseOffset(
395             CORINFO_CLASS_HANDLE classHnd, 
396             DWORD * pBaseOffset);
397
398     BOOL NeedsTypeLayoutCheck(CORINFO_CLASS_HANDLE classHnd);
399     void EncodeTypeLayout(CORINFO_CLASS_HANDLE classHandle, SigBuilder * pSigBuilder);
400
401     BOOL AreAllClassesFullyLoaded(CORINFO_MODULE_HANDLE moduleHandle);
402
403     int GetVersionResilientTypeHashCode(CORINFO_MODULE_HANDLE moduleHandle, mdToken token);
404
405     int GetVersionResilientMethodHashCode(CORINFO_METHOD_HANDLE methodHandle);
406 #endif
407
408     BOOL HasCustomAttribute(CORINFO_METHOD_HANDLE method, LPCSTR customAttributeName);
409
410     //--------------------------------------------------------------------
411     // ZapperLoaderModules and the ZapperLoaderModuleTable
412     //
413     // When NGEN'ing we want to adjust the
414     // places where some items (i.e. generic instantiations) are placed, in order to get some of them
415     // placed into the module we are compiling.  However, the
416     // results of ComputeLoaderModule must be stable for the duration
417     // of an entire instance of the VM, i.e. for the duration of a compilation 
418     // process.  Thus each time we place an item into a non-standard LoaderModule we record 
419     // that fact.
420
421     Module *LookupZapperLoaderModule(const ZapperLoaderModuleTableKey *pKey)
422     {
423         WRAPPER_NO_CONTRACT;
424         const ZapperLoaderModuleTableEntry *pEntry = m_ZapperLoaderModuleTable.LookupPtr(pKey);
425         if (pEntry)
426             return pEntry->result;
427         return NULL;
428     }
429
430     void RecordZapperLoaderModule(const ZapperLoaderModuleTableKey *pKey,
431                                   Module *pZapperLoaderModuleTable)
432     {
433         CONTRACTL
434         {
435             THROWS;
436             GC_NOTRIGGER;
437             SO_TOLERANT;
438             MODE_ANY;
439         }
440         CONTRACTL_END;
441         ZapperLoaderModuleTableEntry entry(*pKey, pZapperLoaderModuleTable);
442         m_ZapperLoaderModuleTable.Add(entry);
443     }
444
445     ZapperLoaderModuleTable m_ZapperLoaderModuleTable;
446     
447 private:
448     BOOL m_fCachingOfInliningHintsEnabled;
449     BOOL m_fGeneratingNgenPDB;
450 };
451
452 extern CEECompileInfo *g_pCEECompileInfo;
453
454 BOOL IsNgenPDBCompilationProcess();
455
456 //
457 // See comment at top of file for an explanation on the preloader
458 // architecture.
459 //
460
461 class CEEPreloader : public ICorCompilePreloader
462 {
463   private:
464     DataImage              *m_image;
465     ICorCompileDataStore   *m_pData;
466
467     class MethodSetTraits : public NoRemoveSHashTraits< DefaultSHashTraits<MethodDesc *> >
468     {
469     public:
470         typedef MethodDesc *key_t;
471         static MethodDesc * GetKey(MethodDesc *md) { return md; }
472         static count_t Hash(MethodDesc *md) { return (count_t) (UINT_PTR) md; }
473         static BOOL Equals(MethodDesc *md1, MethodDesc *md2)
474         {
475             return md1 == md2;
476         }
477     };
478
479     class TypeSetTraits : public NoRemoveSHashTraits< DefaultSHashTraits<TypeHandle> >
480     {
481     public:
482         typedef TypeHandle key_t;
483         static const TypeHandle Null() { return TypeHandle(); }
484         static bool IsNull(const TypeHandle &th) { return !!th.IsNull(); }
485         static TypeHandle GetKey(TypeHandle th) { return th; }
486         static count_t Hash(TypeHandle th) { return (count_t) th.AsTAddr(); }
487         static BOOL Equals(TypeHandle th1, TypeHandle th2) { return th1 == th2; }
488     };
489
490     // Cached results of instantiations triage
491     SHash<TypeSetTraits>    m_acceptedTypes;
492     SHash<MethodSetTraits>  m_acceptedMethods;
493     SHash<TypeSetTraits>    m_rejectedTypes;
494     SHash<MethodSetTraits>  m_rejectedMethods;
495
496 #ifdef FEATURE_FULL_NGEN
497     // Tentatively accepted instantiations
498     InlineSArray<TypeHandle, 20>    m_speculativeTypes;
499     BOOL                            m_fSpeculativeTriage;
500     BOOL                            m_fDictionariesPopulated;
501 #endif
502
503     struct CompileMethodEntry
504     {
505         MethodDesc * pMD;
506 #ifndef FEATURE_FULL_NGEN // Unreferenced methods
507         bool fReferenced; // true when this method was referenced by other code
508         bool fScheduled;  // true when this method was scheduled for compilation
509 #endif
510     };
511
512     class CompileMethodSetTraits : public NoRemoveSHashTraits< DefaultSHashTraits<CompileMethodEntry> >
513     {
514     public:
515         typedef MethodDesc *key_t;
516         static MethodDesc * GetKey(CompileMethodEntry e) { return e.pMD; }
517         static count_t Hash(MethodDesc *md) { return (count_t) (UINT_PTR) md; }
518         static BOOL Equals(MethodDesc *md1, MethodDesc *md2)
519         {
520             return md1 == md2;
521         }
522         static const CompileMethodEntry Null() { CompileMethodEntry e; e.pMD = NULL; return e; }
523         static bool IsNull(const CompileMethodEntry &e) { return e.pMD == NULL; }
524     };
525
526     SHash<CompileMethodSetTraits> m_compileMethodsHash;
527
528     // Array of methods that we need to compile.
529     SArray<MethodDesc*> m_uncompiledMethods;
530
531     int m_methodCompileLimit;
532
533     void AppendUncompiledMethod(MethodDesc *pMD)
534     {
535         STANDARD_VM_CONTRACT;
536         if (m_methodCompileLimit > 0)
537         {
538             m_uncompiledMethods.Append(pMD);
539             m_methodCompileLimit--;
540         }
541     }
542
543     struct DuplicateMethodEntry
544     {
545         MethodDesc * pMD;
546         MethodDesc * pDuplicateMD;
547     };
548
549     class DuplicateMethodTraits : public NoRemoveSHashTraits< DefaultSHashTraits<DuplicateMethodEntry> >
550     {
551     public:
552         typedef MethodDesc *key_t;
553         static MethodDesc * GetKey(DuplicateMethodEntry e) { return e.pMD; }
554         static count_t Hash(MethodDesc *md) { return (count_t) (UINT_PTR) md; }
555         static BOOL Equals(MethodDesc *md1, MethodDesc *md2)
556         {
557             return md1 == md2;
558         }
559         static const DuplicateMethodEntry Null() { DuplicateMethodEntry e; e.pMD = NULL; return e; }
560         static bool IsNull(const DuplicateMethodEntry &e) { return e.pMD == NULL; }
561     };
562
563     SHash<DuplicateMethodTraits> m_duplicateMethodsHash;
564
565     MethodDesc * CompileMethodStubIfNeeded(
566             MethodDesc *pMD,
567             MethodDesc *pStubMD,
568             ICorCompilePreloader::CORCOMPILE_CompileStubCallback pfnCallback,
569             LPVOID pCallbackContext);
570
571   public:
572     CEEPreloader(Module *pModule,
573                  ICorCompileDataStore *pData);
574     virtual ~CEEPreloader();
575
576     void Preload(CorProfileData * profileData);
577     DataImage * GetDataImage() { LIMITED_METHOD_CONTRACT; return m_image; }
578     ICorCompileDataStore * GetDataStore() { LIMITED_METHOD_CONTRACT; return m_pData; }
579
580     //
581     // ICorCompilerPreloader
582     //
583
584     DWORD MapMethodEntryPoint(CORINFO_METHOD_HANDLE handle);
585     DWORD MapClassHandle(CORINFO_CLASS_HANDLE handle);
586     DWORD MapMethodHandle(CORINFO_METHOD_HANDLE handle);
587     DWORD MapFieldHandle(CORINFO_FIELD_HANDLE handle);
588     DWORD MapAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE handle);
589     DWORD MapGenericHandle(CORINFO_GENERIC_HANDLE handle);    
590     DWORD MapModuleIDHandle(CORINFO_MODULE_HANDLE handle);
591
592     void AddMethodToTransitiveClosureOfInstantiations(CORINFO_METHOD_HANDLE handle);
593     void AddTypeToTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE handle);
594     BOOL IsMethodInTransitiveClosureOfInstantiations(CORINFO_METHOD_HANDLE handle);
595     BOOL IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE handle);
596
597     void MethodReferencedByCompiledCode(CORINFO_METHOD_HANDLE handle);
598
599     BOOL IsUncompiledMethod(CORINFO_METHOD_HANDLE handle);
600
601 private:
602     void AddToUncompiledMethods(MethodDesc *pMethod, BOOL fForStubs);
603
604     void ApplyTypeDependencyProductionsForType(TypeHandle t);
605     void ApplyTypeDependencyForSZArrayHelper(MethodTable * pInterfaceMT, TypeHandle elemTypeHnd);
606
607     friend class Module;
608     void TriageTypeForZap(TypeHandle th, BOOL fAcceptIfNotSure, BOOL fExpandDependencies = TRUE);
609     void TriageMethodForZap(MethodDesc* pMethod, BOOL fAcceptIfNotSure, BOOL fExpandDependencies = TRUE);
610
611     void ExpandTypeDependencies(TypeHandle th);
612     void ExpandMethodDependencies(MethodDesc * pMD);
613
614     void TriageTypeSpecsFromSoftBoundModule(Module * pSoftBoundModule);
615     void TriageTypeFromSoftBoundModule(TypeHandle th, Module * pSoftBoundModule);
616     void TriageSpeculativeType(TypeHandle th);
617     void TriageSpeculativeInstantiations();
618
619     // Returns TRUE if new types or methods have been added by the triage
620     BOOL TriageForZap(BOOL fAcceptIfNotSure, BOOL fExpandDependencies = TRUE);
621
622 public:
623     CORINFO_METHOD_HANDLE NextUncompiledMethod();
624
625     void PrePrepareMethodIfNecessary(CORINFO_METHOD_HANDLE hMethod);
626
627     void GenerateMethodStubs(
628             CORINFO_METHOD_HANDLE hMethod,
629             bool                  fNgenProfileImage,
630             CORCOMPILE_CompileStubCallback pfnCallback,
631             LPVOID                pCallbackContext);
632
633     bool IsDynamicMethod(CORINFO_METHOD_HANDLE hMethod);
634     void SetMethodProfilingFlags(CORINFO_METHOD_HANDLE hMethod, DWORD flags);
635
636     bool CanSkipMethodPreparation (
637             CORINFO_METHOD_HANDLE   callerHnd,      /* IN  */
638             CORINFO_METHOD_HANDLE   calleeHnd,      /* IN  */
639             CorInfoIndirectCallReason *pReason = NULL,
640             CORINFO_ACCESS_FLAGS    accessFlags = CORINFO_ACCESS_ANY);
641
642     BOOL CanEmbedClassID     (CORINFO_CLASS_HANDLE    typeHandle);
643     BOOL CanEmbedModuleID    (CORINFO_MODULE_HANDLE   moduleHandle);    
644     BOOL CanEmbedModuleHandle(CORINFO_MODULE_HANDLE   moduleHandle);
645     BOOL CanEmbedClassHandle (CORINFO_CLASS_HANDLE    typeHandle);
646     BOOL CanEmbedMethodHandle(CORINFO_METHOD_HANDLE   methodHandle, 
647                               CORINFO_METHOD_HANDLE   contextHandle);
648     BOOL CanEmbedFieldHandle (CORINFO_FIELD_HANDLE    fieldHandle);
649
650     BOOL CanPrerestoreEmbedClassHandle (CORINFO_CLASS_HANDLE  classHnd);
651     BOOL CanPrerestoreEmbedMethodHandle(CORINFO_METHOD_HANDLE methodHnd);
652
653     BOOL CanEmbedFunctionEntryPoint(CORINFO_METHOD_HANDLE   methodHandle,
654                                     CORINFO_METHOD_HANDLE   contextHandle,
655                                     CORINFO_ACCESS_FLAGS    accessFlags = CORINFO_ACCESS_ANY);
656
657     BOOL DoesMethodNeedRestoringBeforePrestubIsRun(CORINFO_METHOD_HANDLE   methodHandle);
658
659     BOOL CanSkipDependencyActivation(CORINFO_METHOD_HANDLE   context,
660                                      CORINFO_MODULE_HANDLE   moduleFrom,
661                                      CORINFO_MODULE_HANDLE   moduleTo);
662
663     CORINFO_MODULE_HANDLE GetPreferredZapModuleForClassHandle(CORINFO_CLASS_HANDLE classHnd);
664
665     void NoteDeduplicatedCode(CORINFO_METHOD_HANDLE method, CORINFO_METHOD_HANDLE duplicateMethod);
666
667     CORINFO_METHOD_HANDLE LookupMethodDef(mdMethodDef token);
668
669     CorCompileILRegion GetILRegion(mdMethodDef token);
670
671     CORINFO_CLASS_HANDLE  FindTypeForProfileEntry(CORBBTPROF_BLOB_PARAM_SIG_ENTRY * profileBlobEntry);
672     CORINFO_METHOD_HANDLE FindMethodForProfileEntry(CORBBTPROF_BLOB_PARAM_SIG_ENTRY * profileBlobEntry);
673
674     void ReportInlining(CORINFO_METHOD_HANDLE inliner, CORINFO_METHOD_HANDLE inlinee);
675     
676     void Link();
677     void FixupRVAs();
678
679     void SetRVAsForFields(IMetaDataEmit * pEmit);
680
681     void GetRVAFieldData(mdFieldDef fd, PVOID * ppData, DWORD * pcbSize, DWORD * pcbAlignment);
682
683     ULONG Release();
684
685     void Error(mdToken token, Exception * pException);
686 };
687
688
689 struct RefCache
690 {
691     RefCache(Module *pModule)
692     {
693         CONTRACTL
694         {
695             NOTHROW;
696             GC_NOTRIGGER;
697             FORBID_FAULT;
698         }
699         CONTRACTL_END
700
701
702         m_pModule = pModule;
703
704         {
705             // HashMap::Init can throw due to OOM. Our ctor can't. Since this whole
706             // thing is for use inside CEECompileInfo methods, it doesn't make sense to
707             // use an exception model. Thus we probably have to move the hashmap init
708             // calls out of the ctor so can catch these exceptions and translate them to
709             // hresults.
710             // 
711             CONTRACT_VIOLATION(ThrowsViolation|FaultViolation);
712
713             m_sAssemblyRefMap.Init(FALSE,NULL);
714         }
715     }
716
717     Module *m_pModule;
718
719     HashMap m_sAssemblyRefMap;
720 };
721
722 struct AssemblySpecDefRefMapEntry {
723     AssemblySpec * m_pDef;
724     AssemblySpec * m_pRef;
725 };
726
727 class AssemblySpecDefRefMapTraits : public NoRemoveSHashTraits<DefaultSHashTraits<AssemblySpecDefRefMapEntry> >
728 {
729 public:
730     typedef const AssemblySpec *key_t;
731     static const AssemblySpec * GetKey(const AssemblySpecDefRefMapEntry &e) { return e.m_pDef; }
732
733     static count_t Hash(const AssemblySpec * k)
734     {
735         return const_cast<AssemblySpec *>(k)->Hash();
736     }
737
738     static BOOL Equals(const AssemblySpec * lhs, const AssemblySpec * rhs)
739     {
740         return const_cast<AssemblySpec *>(lhs)->CompareEx(const_cast<AssemblySpec *>(rhs), AssemblySpec::ASC_DefinitionEquality);
741     }
742
743     static const AssemblySpecDefRefMapEntry Null() { AssemblySpecDefRefMapEntry e; e.m_pDef = NULL; return e; }
744     static bool IsNull(const AssemblySpecDefRefMapEntry &e) { return e.m_pDef == NULL; }
745
746     void OnDestructPerEntryCleanupAction(const AssemblySpecDefRefMapEntry& e)
747     {
748         WRAPPER_NO_CONTRACT;
749         delete e.m_pDef;
750         delete e.m_pRef;
751     }
752     static const bool s_DestructPerEntryCleanupAction = true;
753 };
754
755 typedef SHash<AssemblySpecDefRefMapTraits> AssemblySpecMapDefRefMapTable;
756
757 class CompilationDomain : public AppDomain, 
758                           public ICorCompilationDomain
759 {
760 #ifndef FEATURE_CORECLR
761     VPTR_MULTI_VTABLE_CLASS(CompilationDomain, AppDomain);
762 #endif
763
764  public:
765     BOOL                    m_fForceDebug; 
766     BOOL                    m_fForceProfiling;
767     BOOL                    m_fForceInstrument;
768
769     // TODO:  During ngen, we need to determine whether we can call NeedsRestore
770     // before the preloader has been initialized.  This is accomplished via this
771     // method.  This code needs to be cleaned up.  See bug #284709 for background.
772     BOOL canCallNeedsRestore() { return  (m_pTargetImage != NULL); };
773
774     // DDB 175659: Make sure that canCallNeedsRestore() returns FALSE during compilation 
775     // domain shutdown.
776     void setCannotCallNeedsRestore() { m_pTargetImage = NULL; }
777     
778   private:
779
780     Assembly                *m_pTargetAssembly;     // Assembly being compiled
781     Module                  *m_pTargetModule;       // Module currently being compiled. Needed for multi-module assemblies
782     DataImage               *m_pTargetImage;        // Data image
783     CEEPreloader            *m_pTargetPreloader;
784
785     ReleaseHolder<IMetaDataAssemblyEmit>    m_pEmit;
786
787     NewHolder<AssemblySpecHash>             m_pDependencyRefSpecs;
788
789     AssemblySpecMapDefRefMapTable           m_dependencyDefRefMap;
790
791     CORCOMPILE_DEPENDENCY   *m_pDependencies;
792     USHORT                   m_cDependenciesCount, m_cDependenciesAlloc;
793
794     CQuickArray<RefCache*> m_rRefCaches;
795
796     HRESULT AddDependencyEntry(PEAssembly *pFile, mdAssemblyRef ref,mdAssemblyRef def);
797     void ReleaseDependencyEmitter();
798
799 #ifndef FEATURE_CORECLR // hardbinding
800     PtrHashMap              m_hardBoundModules;     // Hard dependency on native image of these dependency modules
801     PtrHashMap              m_cantHardBindModules;
802     void UpdateDependencyEntryForHardBind(PEAssembly * pDependencyAssembly);
803     void IncludeHardBindClosure(PEAssembly * pDependencyAssembly);
804     void CheckHardBindToZapFile(SString dependencyNameFromCustomAttribute);
805     void CheckLoadHints();
806 #endif
807
808   public:
809
810 #ifndef DACCESS_COMPILE
811     CompilationDomain(BOOL fForceDebug = FALSE, 
812                       BOOL fForceProfiling = FALSE,
813                       BOOL fForceInstrument = FALSE);
814     ~CompilationDomain();
815 #endif
816
817     void Init();
818
819     HRESULT AddDependency(AssemblySpec *pRefSpec, PEAssembly *pFile);
820
821     AssemblySpec* FindAssemblyRefSpecForDefSpec(
822         AssemblySpec* pDefSpec);
823
824     PEAssembly *BindAssemblySpec(
825         AssemblySpec *pSpec,
826         BOOL fThrowOnFileNotFound,
827         BOOL fRaisePrebindEvents,
828         StackCrawlMark *pCallerStackMark = NULL,
829         AssemblyLoadSecurity *pLoadSecurity = NULL,
830         BOOL fUseHostBinderIfAvailable = TRUE) DAC_EMPTY_RET(NULL);
831
832     BOOL CanEagerBindToZapFile(Module *targetModule, BOOL limitToHardBindList = TRUE);
833
834 #ifndef FEATURE_CORECLR // hardbinding
835     PtrHashMap::PtrIterator IterateHardBoundModules();
836
837     // List of full display names of assemblies to hard-bind to
838     SArray<SString,FALSE> m_assemblyHardBindList;
839     BOOL                  m_useHardBindList;
840     BOOL IsInHardBindRequestList(Assembly * pAssembly);
841     BOOL IsInHardBindRequestList(PEAssembly * pAssembly);
842     BOOL IsSafeToHardBindTo(PEAssembly * pAssembly);
843
844     void SetAssemblyHardBindList(
845                         __in_ecount( cHardBindList )
846                             LPWSTR *pHardBindList,
847                         DWORD  cHardBindList);
848 #endif
849
850 #if defined(CROSSGEN_COMPILE) && !defined(FEATURE_CORECLR)
851     void ComputeAssemblyHardBindList(IMDInternalImport * pImport);
852     BOOL IsInHardBindList(SString& simpleName);
853
854     static BOOL FindImage(const SString& fileName, MDInternalImportFlags flags, PEImage ** ppImage);
855 #endif
856
857     // Returns NULL on out-of-memory
858     RefCache *GetRefCache(Module *pModule)
859     {
860         CONTRACTL
861         {
862             NOTHROW;
863             GC_NOTRIGGER;
864             INJECT_FAULT(return NULL;);
865         }
866         CONTRACTL_END
867
868         unsigned uSize = (unsigned) m_rRefCaches.Size();
869         for (unsigned i = 0; i < uSize; i++)
870             if (m_rRefCaches[i]->m_pModule == pModule)
871                 return m_rRefCaches[i];
872
873         // Add a new cache entry
874         HRESULT hr;
875         
876         if (FAILED(hr = m_rRefCaches.ReSizeNoThrow(uSize + 1)))
877         {
878             _ASSERTE(hr == E_OUTOFMEMORY);
879             return NULL;
880         }
881         
882         m_rRefCaches[uSize] = new (nothrow) RefCache(pModule);
883         return m_rRefCaches[uSize];
884     }
885
886     void SetTarget(Assembly * pAssembly, Module *pModule);
887     
888     void SetTargetImage(DataImage * pImage, CEEPreloader * pPreloader);
889     DataImage * GetTargetImage() { LIMITED_METHOD_CONTRACT; return m_pTargetImage; }
890
891     Assembly * GetTargetAssembly()
892         { LIMITED_METHOD_CONTRACT; return m_pTargetAssembly; }
893     Module * GetTargetModule()
894         { LIMITED_METHOD_CONTRACT; return m_pTargetModule; }
895
896     // ICorCompilationDomain
897
898     HRESULT SetContextInfo(LPCWSTR exePath, BOOL isExe) DAC_EMPTY_RET(E_FAIL);
899     HRESULT GetDependencies(CORCOMPILE_DEPENDENCY **ppDependencies,
900                             DWORD *cDependencies) DAC_EMPTY_RET(E_FAIL);
901 #ifdef FEATURE_FUSION
902     HRESULT GetIBindContext(IBindContext **ppBindCtx) DAC_EMPTY_RET(E_FAIL);
903 #endif
904
905 #ifdef CROSSGEN_COMPILE
906     HRESULT SetPlatformWinmdPaths(LPCWSTR pwzPlatformWinmdPaths) DAC_EMPTY_RET(E_FAIL);
907 #endif
908
909     void SetDependencyEmitter(IMetaDataAssemblyEmit *pEmitter);
910 };
911
912 #endif // FEATURE_NATIVE_IMAGE_GENERATION
913
914 #endif // COMPILE_H_