Merge pull request #9525 from danmosemsft/defines2
[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
239     BOOL CheckAssemblyZap(
240         CORINFO_ASSEMBLY_HANDLE assembly, 
241       __out_ecount_opt(*cAssemblyManifestModulePath) 
242         LPWSTR                  assemblyManifestModulePath, 
243         LPDWORD                 cAssemblyManifestModulePath);
244
245     HRESULT SetCompilationTarget(CORINFO_ASSEMBLY_HANDLE     assembly,
246                                  CORINFO_MODULE_HANDLE       module);
247
248     IMDInternalImport * GetAssemblyMetaDataImport(CORINFO_ASSEMBLY_HANDLE scope);
249
250     IMDInternalImport * GetModuleMetaDataImport(CORINFO_MODULE_HANDLE scope);
251
252     CORINFO_MODULE_HANDLE GetAssemblyModule(CORINFO_ASSEMBLY_HANDLE module);
253
254     CORINFO_ASSEMBLY_HANDLE GetModuleAssembly(CORINFO_MODULE_HANDLE module);
255
256     PEDecoder * GetModuleDecoder(CORINFO_MODULE_HANDLE scope);
257
258     void GetModuleFileName(CORINFO_MODULE_HANDLE module,
259                            SString               &result);
260
261     void EncodeModuleAsIndexes( CORINFO_MODULE_HANDLE   fromHandle,
262                                 CORINFO_MODULE_HANDLE   handle,
263                                 DWORD                   *pAssemblyIndex,
264                                 DWORD                   *pModuleIndex,
265                                 IMetaDataAssemblyEmit   *pAssemblyEmit); 
266
267     void EncodeClass(  CORINFO_MODULE_HANDLE   referencingModule,
268                        CORINFO_CLASS_HANDLE    classHandle,
269                        SigBuilder              *pSigBuilder,
270                        LPVOID                  encodeContext,
271                        ENCODEMODULE_CALLBACK   pfnEncodeModule);
272
273     void EncodeMethod( CORINFO_MODULE_HANDLE   referencingModule,
274                        CORINFO_METHOD_HANDLE   methHnd,
275                        SigBuilder              *pSigBuilder,
276                        LPVOID                  encodeContext,
277                        ENCODEMODULE_CALLBACK   pfnEncodeModule,
278                        CORINFO_RESOLVED_TOKEN  *pResolvedToken,
279                        CORINFO_RESOLVED_TOKEN  *pConstrainedResolvedToken,
280                        BOOL                    fEncodeUsingResolvedTokenSpecStreams);
281
282     virtual mdToken TryEncodeMethodAsToken(CORINFO_METHOD_HANDLE handle, 
283                                            CORINFO_RESOLVED_TOKEN * pResolvedToken,
284                                            CORINFO_MODULE_HANDLE * referencingModule);
285
286     virtual DWORD TryEncodeMethodSlot(CORINFO_METHOD_HANDLE handle);
287
288     void EncodeField(  CORINFO_MODULE_HANDLE   referencingModule,
289                        CORINFO_FIELD_HANDLE    handle,
290                        SigBuilder              *pSigBuilder,
291                        LPVOID                  encodeContext,
292                        ENCODEMODULE_CALLBACK   pfnEncodeModule,
293                        CORINFO_RESOLVED_TOKEN  *pResolvedToken,
294                        BOOL                    fEncodeUsingResolvedTokenSpecStreams);
295
296     // Encode generic dictionary signature
297     virtual void EncodeGenericSignature(
298             LPVOID signature,
299             BOOL fMethod,
300             SigBuilder * pSigBuilder,
301             LPVOID encodeContext,
302             ENCODEMODULE_CALLBACK pfnEncodeModule);
303
304
305     BOOL IsEmptyString(mdString token,
306                        CORINFO_MODULE_HANDLE module);
307
308     BOOL IsNativeCallableMethod(CORINFO_METHOD_HANDLE handle);
309
310     BOOL IsCachingOfInliningHintsEnabled()
311     {
312         return m_fCachingOfInliningHintsEnabled;
313     }
314
315     void DisableCachingOfInliningHints()
316     {
317         m_fCachingOfInliningHintsEnabled = FALSE;
318     }
319
320     HRESULT GetTypeDef(   CORINFO_CLASS_HANDLE    classHandle,
321                           mdTypeDef               *token);
322     HRESULT GetMethodDef( CORINFO_METHOD_HANDLE   methodHandle,
323                           mdMethodDef             *token);
324     HRESULT GetFieldDef(  CORINFO_FIELD_HANDLE    fieldHandle,
325                           mdFieldDef              *token);
326
327     void SetAssemblyHardBindList(__in_ecount( cHardBindList )
328                                  LPWSTR *pHardBindList,
329                                  DWORD cHardBindList);
330
331     CORINFO_MODULE_HANDLE GetLoaderModuleForMscorlib();
332     CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableType(CORINFO_CLASS_HANDLE classHandle);
333     CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableMethod(CORINFO_METHOD_HANDLE methodHandle);
334     CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableField(CORINFO_FIELD_HANDLE fieldHandle);
335
336     ICorCompilePreloader * PreloadModule(CORINFO_MODULE_HANDLE   moduleHandle,
337                                     ICorCompileDataStore    *pData,
338                                     CorProfileData          *profileData);
339
340 #ifdef FEATURE_FUSION
341     HRESULT GetAssemblyName(
342             CORINFO_ASSEMBLY_HANDLE hAssembly,
343             DWORD                   dwFlags,
344             __out_z LPWSTR          wzAssemblyName, 
345             LPDWORD                 cchAssemblyName);
346 #endif //FEATURE_FUSION
347     
348     HRESULT GetLoadHint(CORINFO_ASSEMBLY_HANDLE   hAssembly,
349                         CORINFO_ASSEMBLY_HANDLE hAssemblyDependency,
350                         LoadHintEnum           *loadHint,
351                         LoadHintEnum           *defaultLoadHint);
352
353     HRESULT GetAssemblyVersionInfo(CORINFO_ASSEMBLY_HANDLE Handle, 
354                                     CORCOMPILE_VERSION_INFO *pInfo);
355
356     void GetAssemblyCodeBase(CORINFO_ASSEMBLY_HANDLE hAssembly,
357                              SString                &result);
358
359     void GetCallRefMap(CORINFO_METHOD_HANDLE hMethod, 
360                        GCRefMapBuilder * pBuilder);
361
362     void CompressDebugInfo(
363                                     IN ICorDebugInfo::OffsetMapping * pOffsetMapping,
364                                     IN ULONG            iOffsetMapping,
365                                     IN ICorDebugInfo::NativeVarInfo * pNativeVarInfo,
366                                     IN ULONG            iNativeVarInfo,
367                                     IN OUT SBuffer    * pDebugInfoBuffer);
368
369     HRESULT SetVerboseLevel(
370                                     IN  VerboseLevel        level);
371
372     HRESULT GetBaseJitFlags(
373             IN  CORINFO_METHOD_HANDLE    hMethod,
374             OUT CORJIT_FLAGS            *pFlags);
375
376 #ifdef _WIN64
377     SIZE_T  getPersonalityValue();
378 #endif
379
380     void* GetStubSize(void *pStubAddress, DWORD *pSizeToCopy);
381
382     HRESULT GetStubClone(void *pStub, BYTE *pBuffer, DWORD dwBufferSize);
383
384     BOOL GetIsGeneratingNgenPDB();
385     void SetIsGeneratingNgenPDB(BOOL fGeneratingNgenPDB);
386
387 #ifdef FEATURE_READYTORUN_COMPILER
388     CORCOMPILE_FIXUP_BLOB_KIND GetFieldBaseOffset(
389             CORINFO_CLASS_HANDLE classHnd, 
390             DWORD * pBaseOffset);
391
392     BOOL NeedsTypeLayoutCheck(CORINFO_CLASS_HANDLE classHnd);
393     void EncodeTypeLayout(CORINFO_CLASS_HANDLE classHandle, SigBuilder * pSigBuilder);
394
395     BOOL AreAllClassesFullyLoaded(CORINFO_MODULE_HANDLE moduleHandle);
396
397     int GetVersionResilientTypeHashCode(CORINFO_MODULE_HANDLE moduleHandle, mdToken token);
398
399     int GetVersionResilientMethodHashCode(CORINFO_METHOD_HANDLE methodHandle);
400 #endif
401
402     BOOL HasCustomAttribute(CORINFO_METHOD_HANDLE method, LPCSTR customAttributeName);
403
404     //--------------------------------------------------------------------
405     // ZapperLoaderModules and the ZapperLoaderModuleTable
406     //
407     // When NGEN'ing we want to adjust the
408     // places where some items (i.e. generic instantiations) are placed, in order to get some of them
409     // placed into the module we are compiling.  However, the
410     // results of ComputeLoaderModule must be stable for the duration
411     // of an entire instance of the VM, i.e. for the duration of a compilation 
412     // process.  Thus each time we place an item into a non-standard LoaderModule we record 
413     // that fact.
414
415     Module *LookupZapperLoaderModule(const ZapperLoaderModuleTableKey *pKey)
416     {
417         WRAPPER_NO_CONTRACT;
418         const ZapperLoaderModuleTableEntry *pEntry = m_ZapperLoaderModuleTable.LookupPtr(pKey);
419         if (pEntry)
420             return pEntry->result;
421         return NULL;
422     }
423
424     void RecordZapperLoaderModule(const ZapperLoaderModuleTableKey *pKey,
425                                   Module *pZapperLoaderModuleTable)
426     {
427         CONTRACTL
428         {
429             THROWS;
430             GC_NOTRIGGER;
431             SO_TOLERANT;
432             MODE_ANY;
433         }
434         CONTRACTL_END;
435         ZapperLoaderModuleTableEntry entry(*pKey, pZapperLoaderModuleTable);
436         m_ZapperLoaderModuleTable.Add(entry);
437     }
438
439     ZapperLoaderModuleTable m_ZapperLoaderModuleTable;
440     
441 private:
442     BOOL m_fCachingOfInliningHintsEnabled;
443     BOOL m_fGeneratingNgenPDB;
444 };
445
446 extern CEECompileInfo *g_pCEECompileInfo;
447
448 BOOL IsNgenPDBCompilationProcess();
449
450 //
451 // See comment at top of file for an explanation on the preloader
452 // architecture.
453 //
454
455 class CEEPreloader : public ICorCompilePreloader
456 {
457   private:
458     DataImage              *m_image;
459     ICorCompileDataStore   *m_pData;
460
461     class MethodSetTraits : public NoRemoveSHashTraits< DefaultSHashTraits<MethodDesc *> >
462     {
463     public:
464         typedef MethodDesc *key_t;
465         static MethodDesc * GetKey(MethodDesc *md) { return md; }
466         static count_t Hash(MethodDesc *md) { return (count_t) (UINT_PTR) md; }
467         static BOOL Equals(MethodDesc *md1, MethodDesc *md2)
468         {
469             return md1 == md2;
470         }
471     };
472
473     class TypeSetTraits : public NoRemoveSHashTraits< DefaultSHashTraits<TypeHandle> >
474     {
475     public:
476         typedef TypeHandle key_t;
477         static const TypeHandle Null() { return TypeHandle(); }
478         static bool IsNull(const TypeHandle &th) { return !!th.IsNull(); }
479         static TypeHandle GetKey(TypeHandle th) { return th; }
480         static count_t Hash(TypeHandle th) { return (count_t) th.AsTAddr(); }
481         static BOOL Equals(TypeHandle th1, TypeHandle th2) { return th1 == th2; }
482     };
483
484     // Cached results of instantiations triage
485     SHash<TypeSetTraits>    m_acceptedTypes;
486     SHash<MethodSetTraits>  m_acceptedMethods;
487     SHash<TypeSetTraits>    m_rejectedTypes;
488     SHash<MethodSetTraits>  m_rejectedMethods;
489
490 #ifdef FEATURE_FULL_NGEN
491     // Tentatively accepted instantiations
492     InlineSArray<TypeHandle, 20>    m_speculativeTypes;
493     BOOL                            m_fSpeculativeTriage;
494     BOOL                            m_fDictionariesPopulated;
495 #endif
496
497     struct CompileMethodEntry
498     {
499         MethodDesc * pMD;
500 #ifndef FEATURE_FULL_NGEN // Unreferenced methods
501         bool fReferenced; // true when this method was referenced by other code
502         bool fScheduled;  // true when this method was scheduled for compilation
503 #endif
504     };
505
506     class CompileMethodSetTraits : public NoRemoveSHashTraits< DefaultSHashTraits<CompileMethodEntry> >
507     {
508     public:
509         typedef MethodDesc *key_t;
510         static MethodDesc * GetKey(CompileMethodEntry e) { return e.pMD; }
511         static count_t Hash(MethodDesc *md) { return (count_t) (UINT_PTR) md; }
512         static BOOL Equals(MethodDesc *md1, MethodDesc *md2)
513         {
514             return md1 == md2;
515         }
516         static const CompileMethodEntry Null() { CompileMethodEntry e; e.pMD = NULL; return e; }
517         static bool IsNull(const CompileMethodEntry &e) { return e.pMD == NULL; }
518     };
519
520     SHash<CompileMethodSetTraits> m_compileMethodsHash;
521
522     // Array of methods that we need to compile.
523     SArray<MethodDesc*> m_uncompiledMethods;
524
525     int m_methodCompileLimit;
526
527     void AppendUncompiledMethod(MethodDesc *pMD)
528     {
529         STANDARD_VM_CONTRACT;
530         if (m_methodCompileLimit > 0)
531         {
532             m_uncompiledMethods.Append(pMD);
533             m_methodCompileLimit--;
534         }
535     }
536
537     struct DuplicateMethodEntry
538     {
539         MethodDesc * pMD;
540         MethodDesc * pDuplicateMD;
541     };
542
543     class DuplicateMethodTraits : public NoRemoveSHashTraits< DefaultSHashTraits<DuplicateMethodEntry> >
544     {
545     public:
546         typedef MethodDesc *key_t;
547         static MethodDesc * GetKey(DuplicateMethodEntry e) { return e.pMD; }
548         static count_t Hash(MethodDesc *md) { return (count_t) (UINT_PTR) md; }
549         static BOOL Equals(MethodDesc *md1, MethodDesc *md2)
550         {
551             return md1 == md2;
552         }
553         static const DuplicateMethodEntry Null() { DuplicateMethodEntry e; e.pMD = NULL; return e; }
554         static bool IsNull(const DuplicateMethodEntry &e) { return e.pMD == NULL; }
555     };
556
557     SHash<DuplicateMethodTraits> m_duplicateMethodsHash;
558
559     MethodDesc * CompileMethodStubIfNeeded(
560             MethodDesc *pMD,
561             MethodDesc *pStubMD,
562             ICorCompilePreloader::CORCOMPILE_CompileStubCallback pfnCallback,
563             LPVOID pCallbackContext);
564
565   public:
566     CEEPreloader(Module *pModule,
567                  ICorCompileDataStore *pData);
568     virtual ~CEEPreloader();
569
570     void Preload(CorProfileData * profileData);
571     DataImage * GetDataImage() { LIMITED_METHOD_CONTRACT; return m_image; }
572     ICorCompileDataStore * GetDataStore() { LIMITED_METHOD_CONTRACT; return m_pData; }
573
574     //
575     // ICorCompilerPreloader
576     //
577
578     DWORD MapMethodEntryPoint(CORINFO_METHOD_HANDLE handle);
579     DWORD MapClassHandle(CORINFO_CLASS_HANDLE handle);
580     DWORD MapMethodHandle(CORINFO_METHOD_HANDLE handle);
581     DWORD MapFieldHandle(CORINFO_FIELD_HANDLE handle);
582     DWORD MapAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE handle);
583     DWORD MapGenericHandle(CORINFO_GENERIC_HANDLE handle);    
584     DWORD MapModuleIDHandle(CORINFO_MODULE_HANDLE handle);
585
586     void AddMethodToTransitiveClosureOfInstantiations(CORINFO_METHOD_HANDLE handle);
587     void AddTypeToTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE handle);
588     BOOL IsMethodInTransitiveClosureOfInstantiations(CORINFO_METHOD_HANDLE handle);
589     BOOL IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE handle);
590
591     void MethodReferencedByCompiledCode(CORINFO_METHOD_HANDLE handle);
592
593     BOOL IsUncompiledMethod(CORINFO_METHOD_HANDLE handle);
594
595 private:
596     void AddToUncompiledMethods(MethodDesc *pMethod, BOOL fForStubs);
597
598     void ApplyTypeDependencyProductionsForType(TypeHandle t);
599     void ApplyTypeDependencyForSZArrayHelper(MethodTable * pInterfaceMT, TypeHandle elemTypeHnd);
600
601     friend class Module;
602     void TriageTypeForZap(TypeHandle th, BOOL fAcceptIfNotSure, BOOL fExpandDependencies = TRUE);
603     void TriageMethodForZap(MethodDesc* pMethod, BOOL fAcceptIfNotSure, BOOL fExpandDependencies = TRUE);
604
605     void ExpandTypeDependencies(TypeHandle th);
606     void ExpandMethodDependencies(MethodDesc * pMD);
607
608     void TriageTypeSpecsFromSoftBoundModule(Module * pSoftBoundModule);
609     void TriageTypeFromSoftBoundModule(TypeHandle th, Module * pSoftBoundModule);
610     void TriageSpeculativeType(TypeHandle th);
611     void TriageSpeculativeInstantiations();
612
613     // Returns TRUE if new types or methods have been added by the triage
614     BOOL TriageForZap(BOOL fAcceptIfNotSure, BOOL fExpandDependencies = TRUE);
615
616 public:
617     CORINFO_METHOD_HANDLE NextUncompiledMethod();
618
619     void PrePrepareMethodIfNecessary(CORINFO_METHOD_HANDLE hMethod);
620
621     void GenerateMethodStubs(
622             CORINFO_METHOD_HANDLE hMethod,
623             bool                  fNgenProfileImage,
624             CORCOMPILE_CompileStubCallback pfnCallback,
625             LPVOID                pCallbackContext);
626
627     bool IsDynamicMethod(CORINFO_METHOD_HANDLE hMethod);
628     void SetMethodProfilingFlags(CORINFO_METHOD_HANDLE hMethod, DWORD flags);
629
630     bool CanSkipMethodPreparation (
631             CORINFO_METHOD_HANDLE   callerHnd,      /* IN  */
632             CORINFO_METHOD_HANDLE   calleeHnd,      /* IN  */
633             CorInfoIndirectCallReason *pReason = NULL,
634             CORINFO_ACCESS_FLAGS    accessFlags = CORINFO_ACCESS_ANY);
635
636     BOOL CanEmbedClassID     (CORINFO_CLASS_HANDLE    typeHandle);
637     BOOL CanEmbedModuleID    (CORINFO_MODULE_HANDLE   moduleHandle);    
638     BOOL CanEmbedModuleHandle(CORINFO_MODULE_HANDLE   moduleHandle);
639     BOOL CanEmbedClassHandle (CORINFO_CLASS_HANDLE    typeHandle);
640     BOOL CanEmbedMethodHandle(CORINFO_METHOD_HANDLE   methodHandle, 
641                               CORINFO_METHOD_HANDLE   contextHandle);
642     BOOL CanEmbedFieldHandle (CORINFO_FIELD_HANDLE    fieldHandle);
643
644     BOOL CanPrerestoreEmbedClassHandle (CORINFO_CLASS_HANDLE  classHnd);
645     BOOL CanPrerestoreEmbedMethodHandle(CORINFO_METHOD_HANDLE methodHnd);
646
647     BOOL CanEmbedFunctionEntryPoint(CORINFO_METHOD_HANDLE   methodHandle,
648                                     CORINFO_METHOD_HANDLE   contextHandle,
649                                     CORINFO_ACCESS_FLAGS    accessFlags = CORINFO_ACCESS_ANY);
650
651     BOOL DoesMethodNeedRestoringBeforePrestubIsRun(CORINFO_METHOD_HANDLE   methodHandle);
652
653     BOOL CanSkipDependencyActivation(CORINFO_METHOD_HANDLE   context,
654                                      CORINFO_MODULE_HANDLE   moduleFrom,
655                                      CORINFO_MODULE_HANDLE   moduleTo);
656
657     CORINFO_MODULE_HANDLE GetPreferredZapModuleForClassHandle(CORINFO_CLASS_HANDLE classHnd);
658
659     void NoteDeduplicatedCode(CORINFO_METHOD_HANDLE method, CORINFO_METHOD_HANDLE duplicateMethod);
660
661     CORINFO_METHOD_HANDLE LookupMethodDef(mdMethodDef token);
662
663     CorCompileILRegion GetILRegion(mdMethodDef token);
664
665     CORINFO_CLASS_HANDLE  FindTypeForProfileEntry(CORBBTPROF_BLOB_PARAM_SIG_ENTRY * profileBlobEntry);
666     CORINFO_METHOD_HANDLE FindMethodForProfileEntry(CORBBTPROF_BLOB_PARAM_SIG_ENTRY * profileBlobEntry);
667
668     void ReportInlining(CORINFO_METHOD_HANDLE inliner, CORINFO_METHOD_HANDLE inlinee);
669     
670     void Link();
671     void FixupRVAs();
672
673     void SetRVAsForFields(IMetaDataEmit * pEmit);
674
675     void GetRVAFieldData(mdFieldDef fd, PVOID * ppData, DWORD * pcbSize, DWORD * pcbAlignment);
676
677     ULONG Release();
678
679     void Error(mdToken token, Exception * pException);
680 };
681
682
683 struct RefCache
684 {
685     RefCache(Module *pModule)
686     {
687         CONTRACTL
688         {
689             NOTHROW;
690             GC_NOTRIGGER;
691             FORBID_FAULT;
692         }
693         CONTRACTL_END
694
695
696         m_pModule = pModule;
697
698         {
699             // HashMap::Init can throw due to OOM. Our ctor can't. Since this whole
700             // thing is for use inside CEECompileInfo methods, it doesn't make sense to
701             // use an exception model. Thus we probably have to move the hashmap init
702             // calls out of the ctor so can catch these exceptions and translate them to
703             // hresults.
704             // 
705             CONTRACT_VIOLATION(ThrowsViolation|FaultViolation);
706
707             m_sAssemblyRefMap.Init(FALSE,NULL);
708         }
709     }
710
711     Module *m_pModule;
712
713     HashMap m_sAssemblyRefMap;
714 };
715
716 struct AssemblySpecDefRefMapEntry {
717     AssemblySpec * m_pDef;
718     AssemblySpec * m_pRef;
719 };
720
721 class AssemblySpecDefRefMapTraits : public NoRemoveSHashTraits<DefaultSHashTraits<AssemblySpecDefRefMapEntry> >
722 {
723 public:
724     typedef const AssemblySpec *key_t;
725     static const AssemblySpec * GetKey(const AssemblySpecDefRefMapEntry &e) { return e.m_pDef; }
726
727     static count_t Hash(const AssemblySpec * k)
728     {
729         return const_cast<AssemblySpec *>(k)->Hash();
730     }
731
732     static BOOL Equals(const AssemblySpec * lhs, const AssemblySpec * rhs)
733     {
734         return const_cast<AssemblySpec *>(lhs)->CompareEx(const_cast<AssemblySpec *>(rhs), AssemblySpec::ASC_DefinitionEquality);
735     }
736
737     static const AssemblySpecDefRefMapEntry Null() { AssemblySpecDefRefMapEntry e; e.m_pDef = NULL; return e; }
738     static bool IsNull(const AssemblySpecDefRefMapEntry &e) { return e.m_pDef == NULL; }
739
740     void OnDestructPerEntryCleanupAction(const AssemblySpecDefRefMapEntry& e)
741     {
742         WRAPPER_NO_CONTRACT;
743         delete e.m_pDef;
744         delete e.m_pRef;
745     }
746     static const bool s_DestructPerEntryCleanupAction = true;
747 };
748
749 typedef SHash<AssemblySpecDefRefMapTraits> AssemblySpecMapDefRefMapTable;
750
751 class CompilationDomain : public AppDomain, 
752                           public ICorCompilationDomain
753 {
754
755  public:
756     BOOL                    m_fForceDebug; 
757     BOOL                    m_fForceProfiling;
758     BOOL                    m_fForceInstrument;
759
760     // TODO:  During ngen, we need to determine whether we can call NeedsRestore
761     // before the preloader has been initialized.  This is accomplished via this
762     // method.  This code needs to be cleaned up.  See bug #284709 for background.
763     BOOL canCallNeedsRestore() { return  (m_pTargetImage != NULL); };
764
765     // DDB 175659: Make sure that canCallNeedsRestore() returns FALSE during compilation 
766     // domain shutdown.
767     void setCannotCallNeedsRestore() { m_pTargetImage = NULL; }
768     
769   private:
770
771     Assembly                *m_pTargetAssembly;     // Assembly being compiled
772     Module                  *m_pTargetModule;       // Module currently being compiled. Needed for multi-module assemblies
773     DataImage               *m_pTargetImage;        // Data image
774     CEEPreloader            *m_pTargetPreloader;
775
776     ReleaseHolder<IMetaDataAssemblyEmit>    m_pEmit;
777
778     NewHolder<AssemblySpecHash>             m_pDependencyRefSpecs;
779
780     AssemblySpecMapDefRefMapTable           m_dependencyDefRefMap;
781
782     CORCOMPILE_DEPENDENCY   *m_pDependencies;
783     USHORT                   m_cDependenciesCount, m_cDependenciesAlloc;
784
785     CQuickArray<RefCache*> m_rRefCaches;
786
787     HRESULT AddDependencyEntry(PEAssembly *pFile, mdAssemblyRef ref,mdAssemblyRef def);
788     void ReleaseDependencyEmitter();
789
790
791   public:
792
793 #ifndef DACCESS_COMPILE
794     CompilationDomain(BOOL fForceDebug = FALSE, 
795                       BOOL fForceProfiling = FALSE,
796                       BOOL fForceInstrument = FALSE);
797     ~CompilationDomain();
798 #endif
799
800     void Init();
801
802     HRESULT AddDependency(AssemblySpec *pRefSpec, PEAssembly *pFile);
803
804     AssemblySpec* FindAssemblyRefSpecForDefSpec(
805         AssemblySpec* pDefSpec);
806
807     PEAssembly *BindAssemblySpec(
808         AssemblySpec *pSpec,
809         BOOL fThrowOnFileNotFound,
810         BOOL fRaisePrebindEvents,
811         StackCrawlMark *pCallerStackMark = NULL,
812         AssemblyLoadSecurity *pLoadSecurity = NULL,
813         BOOL fUseHostBinderIfAvailable = TRUE) DAC_EMPTY_RET(NULL);
814
815     BOOL CanEagerBindToZapFile(Module *targetModule, BOOL limitToHardBindList = TRUE);
816
817
818
819     // Returns NULL on out-of-memory
820     RefCache *GetRefCache(Module *pModule)
821     {
822         CONTRACTL
823         {
824             NOTHROW;
825             GC_NOTRIGGER;
826             INJECT_FAULT(return NULL;);
827         }
828         CONTRACTL_END
829
830         unsigned uSize = (unsigned) m_rRefCaches.Size();
831         for (unsigned i = 0; i < uSize; i++)
832             if (m_rRefCaches[i]->m_pModule == pModule)
833                 return m_rRefCaches[i];
834
835         // Add a new cache entry
836         HRESULT hr;
837         
838         if (FAILED(hr = m_rRefCaches.ReSizeNoThrow(uSize + 1)))
839         {
840             _ASSERTE(hr == E_OUTOFMEMORY);
841             return NULL;
842         }
843         
844         m_rRefCaches[uSize] = new (nothrow) RefCache(pModule);
845         return m_rRefCaches[uSize];
846     }
847
848     void SetTarget(Assembly * pAssembly, Module *pModule);
849     
850     void SetTargetImage(DataImage * pImage, CEEPreloader * pPreloader);
851     DataImage * GetTargetImage() { LIMITED_METHOD_CONTRACT; return m_pTargetImage; }
852
853     Assembly * GetTargetAssembly()
854         { LIMITED_METHOD_CONTRACT; return m_pTargetAssembly; }
855     Module * GetTargetModule()
856         { LIMITED_METHOD_CONTRACT; return m_pTargetModule; }
857
858     // ICorCompilationDomain
859
860     HRESULT SetContextInfo(LPCWSTR exePath, BOOL isExe) DAC_EMPTY_RET(E_FAIL);
861     HRESULT GetDependencies(CORCOMPILE_DEPENDENCY **ppDependencies,
862                             DWORD *cDependencies) DAC_EMPTY_RET(E_FAIL);
863 #ifdef FEATURE_FUSION
864     HRESULT GetIBindContext(IBindContext **ppBindCtx) DAC_EMPTY_RET(E_FAIL);
865 #endif
866
867 #ifdef CROSSGEN_COMPILE
868     HRESULT SetPlatformWinmdPaths(LPCWSTR pwzPlatformWinmdPaths) DAC_EMPTY_RET(E_FAIL);
869 #endif
870
871     void SetDependencyEmitter(IMetaDataAssemblyEmit *pEmitter);
872 };
873
874 #endif // FEATURE_NATIVE_IMAGE_GENERATION
875
876 #endif // COMPILE_H_