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