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