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.
9 // NGEN-specific infrastructure for writing PE files.
11 // ======================================================================================
13 #ifndef __ZAPIMAGE_H__
14 #define __ZAPIMAGE_H__
19 class ZapNativeHeader;
21 class ZapDependencies;
22 class ZapCodeManagerEntry;
24 class ZapReadyToRunHeader;
26 class ZapInnerPtrTable;
27 class ZapMethodEntryPointTable;
28 class ZapWrapperTable;
32 class ZapBlobWithRelocs;
34 //class ZapGCInfoTable;
35 #ifdef WIN64EXCEPTIONS
36 class ZapUnwindDataTable;
40 class ZapImportSectionsTable;
41 class ZapImportSectionSignatures;
43 class ZapVirtualSectionsTable;
49 #define SAFERELEASE(p) if ((p) != NULL) { IUnknown * _ = (p); (p) = NULL; _->Release(); };
51 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
52 #define DEFAULT_CODE_BUFFER_INIT 0xcc // breakpoint
54 #define DEFAULT_CODE_BUFFER_INIT 0
59 #define DEFAULT_CODE_ALIGN 16
62 #define DEFAULT_CODE_ALIGN 4
66 #define MINIMUM_CODE_ALIGN 2
68 #define MINIMUM_CODE_ALIGN 4
70 #define MINIMUM_CODE_ALIGN 1
73 // Various zapper hashtables are preallocated based on the size of IL image to reduce amount of
74 // rehashing we have to do. Turn ZAP_HASHTABLE_TUNING on to collect data for the tuning of initial hashtable sizes.
75 // #define ZAP_HASHTABLE_TUNING
77 #ifdef ZAP_HASHTABLE_TUNING
79 #define PREALLOCATE_HASHTABLE(table, quotient, cbILImage) \
80 PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage)
82 #define PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage) \
84 GetSvcLogger()->Printf(W("HashTable:\t%S\t%d\t%f\n"), #table, table.GetCount(), (double)table.GetCount() / (double)cbILImage); \
87 #define PREALLOCATE_ARRAY(array, quotient, cbILImage) \
89 GetSvcLogger()->Printf(W("Array:\t%S\t%d\t%f\n"), #array, array.GetCount(), (double)array.GetCount() / (double)cbILImage); \
92 #else // ZAP_HASHTABLE_TUNING
94 #define PREALLOCATE_HASHTABLE(table, quotient, cbILImage) \
96 COUNT_T nSize = (COUNT_T)(quotient * \
97 ((double)table.s_density_factor_denominator / (double)table.s_density_factor_numerator) * \
99 if (nSize > table.s_minimum_allocation) \
100 table.Reallocate(nSize); \
103 #define PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage)
105 #define PREALLOCATE_ARRAY(array, quotient, cbILImage) \
107 COUNT_T nSize = (COUNT_T)(quotient * \
109 array.Preallocate(nSize); \
112 #endif // ZAP_HASHTABLE_TUNING
114 //---------------------------------------------------------------------------------------
116 // ZapImportSectionType is enum describing import sections allocated in the image
118 enum ZapImportSectionType
120 ZapImportSectionType_Handle, // Unspecified handle
121 ZapImportSectionType_TypeHandle, // Type and method handles have to have their own section so we can restore them correctly
122 ZapImportSectionType_MethodHandle,
124 ZapImportSectionType_PCode, // Code pointers have to be in a own section on ARM because of they are tagged differently
126 ZapImportSectionType_StringHandle, // String handles require special handling for interning
127 ZapImportSectionType_Count,
129 ZapImportSectionType_Hot = 0, // We have two sets of the section - hot and cold
130 ZapImportSectionType_Cold = ZapImportSectionType_Count,
132 ZapImportSectionType_Eager = 2 * ZapImportSectionType_Count, // And one section for eager loaded handles
134 ZapImportSectionType_Total = 2 * ZapImportSectionType_Count + 1,
137 #include "zaprelocs.h"
143 , public ICorCompileDataStore
146 friend class ZapInfo;
147 friend class ZapILMetaData;
148 friend class ZapImportTable;
149 friend class ZapCodeMethodDescs;
150 friend class ZapColdCodeMap;
151 friend class ZapReadyToRunHeader;
161 LPWSTR m_pOutputFileFullName; // Name of the temp ngen file to generate (including the path)
164 // Make all virtual section pointers public for now. It should be cleaned up as we get more sophisticated layout
165 // algorithm in place.
168 ZapPhysicalSection * m_pTextSection;
171 // All virtual sections of the native image in alphabetical order
174 ZapVirtualSection * m_pBaseRelocsSection;
175 ZapVirtualSection * m_pCodeSection;
176 ZapVirtualSection * m_pColdCodeSection;
177 ZapVirtualSection * m_pDebugSection;
178 ZapVirtualSection * m_pDelayLoadInfoDelayListSectionEager;
179 ZapVirtualSection * m_pDelayLoadInfoDelayListSectionCold;
180 ZapVirtualSection * m_pDelayLoadInfoDelayListSectionHot;
181 ZapVirtualSection * m_pDelayLoadInfoTableSection[ZapImportSectionType_Total];
182 ZapVirtualSection * m_pStubsSection;
183 ZapVirtualSection * m_pEETableSection;
184 ZapVirtualSection * m_pExceptionSection;
185 ZapVirtualSection * m_pGCSection;
186 ZapVirtualSection * m_pHeaderSection;
187 ZapVirtualSection * m_pHelperTableSection;
188 ZapVirtualSection * m_pLazyHelperSection;
189 ZapVirtualSection * m_pLazyMethodCallHelperSection;
190 ZapVirtualSection * m_pHotCodeSection;
191 ZapVirtualSection * m_pHotGCSection;
192 ZapVirtualSection * m_pHotTouchedGCSection;
193 ZapVirtualSection * m_pILMetaDataSection;
194 ZapVirtualSection * m_pILSection;
195 ZapVirtualSection * m_pImportTableSection;
196 ZapVirtualSection * m_pInstrumentSection;
197 ZapVirtualSection * m_pMetaDataSection;
198 ZapVirtualSection * m_pReadOnlyDataSection;
199 ZapVirtualSection * m_pResourcesSection;
200 ZapVirtualSection * m_pWin32ResourceSection;
201 ZapVirtualSection * m_pStubDispatchCellSection;
202 ZapVirtualSection * m_pStubDispatchDataSection;
203 ZapVirtualSection * m_pDynamicHelperCellSection;
204 ZapVirtualSection * m_pDynamicHelperDataSection;
205 ZapVirtualSection * m_pVirtualImportThunkSection;
206 ZapVirtualSection * m_pExternalMethodThunkSection;
207 ZapVirtualSection * m_pExternalMethodCellSection;
208 ZapVirtualSection * m_pExternalMethodDataSection;
209 ZapVirtualSection * m_pHotRuntimeFunctionSection;
210 ZapVirtualSection * m_pRuntimeFunctionSection;
211 ZapVirtualSection * m_pColdRuntimeFunctionSection;
212 ZapVirtualSection * m_pHotCodeMethodDescsSection;
213 ZapVirtualSection * m_pCodeMethodDescsSection;
214 ZapVirtualSection * m_pHotRuntimeFunctionLookupSection;
215 ZapVirtualSection * m_pRuntimeFunctionLookupSection;
216 ZapVirtualSection * m_pColdCodeMapSection;
217 #if defined(WIN64EXCEPTIONS)
218 ZapVirtualSection * m_pHotUnwindDataSection;
219 ZapVirtualSection * m_pUnwindDataSection;
220 ZapVirtualSection * m_pColdUnwindDataSection;
221 #endif // defined(WIN64EXCEPTIONS)
223 #ifdef FEATURE_READYTORUN_COMPILER
224 ZapVirtualSection * m_pAvailableTypesSection;
227 // Preloader sections
228 ZapVirtualSection * m_pPreloadSections[CORCOMPILE_SECTION_COUNT];
230 ZapExceptionInfoLookupTable* m_pExceptionInfoLookupTable;
232 // TODO: Remove once all EE datastructures are converted to ZapNodes
233 ICorCompilePreloader * m_pPreloader;
234 DataImage * m_pDataImage;
237 // TODO: The stats should be removed once we have all information available in nidump
238 ZapperStats *m_stats;
241 IMetaDataAssemblyEmit *m_pAssemblyEmit; // native image manifest
242 ZapMetaData * m_pAssemblyMetaData;
244 ZapVersionInfo * m_pVersionInfo;
245 ZapDependencies * m_pDependencies;
247 SString m_pdbFileName;
249 ZapCodeManagerEntry * m_pCodeManagerEntry;
251 ZapBlob * m_pEEInfoTable;
256 ZapImportTable * m_pImportTable;
258 ZapImportSectionsTable * m_pImportSectionsTable;
260 ZapInnerPtrTable * m_pInnerPtrs;
262 ZapMethodEntryPointTable * m_pMethodEntryPoints;
264 ZapWrapperTable * m_pWrappers;
266 ZapBaseRelocs * m_pBaseRelocs;
268 ULONGLONG m_NativeBaseAddress;
270 ULONGLONG GetNativeBaseAddress()
272 return m_NativeBaseAddress;
275 void CalculateZapBaseAddress();
277 // Preallocate hashtables to avoid rehashing
280 ZapGCInfoTable * m_pGCInfoTable;
282 #ifdef WIN64EXCEPTIONS
283 ZapUnwindDataTable * m_pUnwindDataTable;
286 ZapImportSectionSignatures * m_pDelayLoadInfoDataTable[ZapImportSectionType_Total];
287 ZapImportSectionSignatures * m_pStubDispatchDataTable;
288 ZapImportSectionSignatures * m_pExternalMethodDataTable;
289 ZapImportSectionSignatures * m_pDynamicHelperDataTable;
291 ZapVirtualSectionsTable * m_pVirtualSectionsTable;
293 ZapDebugInfoTable * m_pDebugInfoTable;
295 ZapILMetaData * m_pILMetaData;
297 ZapCorHeader * m_pCorHeader;
299 ZapNode * m_pResources;
301 ZapNode * m_pNativeHeader;
303 ZapBlob * m_pNGenPdbDebugData;
305 ULONG m_totalHotCodeSize;
306 ULONG m_totalColdCodeSize;
308 ULONG m_totalCodeSizeInProfiledMethods;
309 ULONG m_totalColdCodeSizeInProfiledMethods;
311 //information to track the boundaries of the different subsections within
313 COUNT_T m_iIBCMethod;
314 COUNT_T m_iGenericsMethod;
315 COUNT_T m_iUntrainedMethod;
321 LPWSTR m_pModuleFileName; // file name of the module being compiled, including path
322 CORINFO_MODULE_HANDLE m_hModule; // Module being compiled
323 PEDecoder m_ModuleDecoder;
324 IMDInternalImport * m_pMDImport;
325 bool m_fManifestModule; // Is this the assembly-manifest-module
326 bool m_fHaveProfileData;
328 ZapNode ** m_pHelperThunks; // Array of on demand allocated JIT helper thunks
334 BYTE * m_profileDataFile;
335 BYTE * m_pRawProfileData;
336 COUNT_T m_cRawProfileData;
337 CorProfileData * m_pCorProfileData;
341 // Failure status values are negative
345 // Info status values are [0..9]
347 COMPILE_EXCLUDED = 1,
348 COMPILE_HOT_EXCLUDED = 2,
349 COMPILE_COLD_EXCLUDED = 3,
351 // Successful status values are 10 or greater
352 COMPILE_SUCCEED = 10,
353 ALREADY_COMPILED = 11
357 // A hash table entry that contains the profile infomation and the CompileStatus for a given method
358 struct ProfileDataHashEntry
360 mdMethodDef md; // The method.token, also used as the key for the ProfileDataHashTable
361 DWORD size; // The size of the CORBBTPROF_BLOCK_DATA region, set by ZapImage::hashBBProfileData()
362 ULONG pos; // the offset to the CORBBTPROF_BLOCK_DATA region, set by ZapImage::hashBBProfileData()
364 unsigned flags; // The methodProfilingDataFlags, set by ZapImage::CompileHotRegion()
365 CompileStatus status; // The compileResult, set by ZapImage::CompileHotRegion()
368 class ProfileDataHashTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ProfileDataHashEntry> >
371 typedef const mdMethodDef key_t;
373 static key_t GetKey(element_t e)
375 LIMITED_METHOD_CONTRACT;
378 static BOOL Equals(key_t k1, key_t k2)
380 LIMITED_METHOD_CONTRACT;
383 static count_t Hash(key_t k)
385 LIMITED_METHOD_CONTRACT;
389 static const element_t Null()
391 LIMITED_METHOD_CONTRACT;
392 ProfileDataHashEntry e;
397 e.status = NOT_COMPILED;
401 static bool IsNull(const element_t &e)
403 LIMITED_METHOD_CONTRACT;
404 // returns true if both md and pos are zero
405 return (e.md == 0) && (e.pos == 0);
408 typedef SHash<ProfileDataHashTraits> ProfileDataHashTable;
410 ProfileDataHashTable profileDataHashTable;
412 SArray<SString, FALSE> fileNotFoundErrorsTable;
413 void FileNotFoundError(LPCWSTR pszMessage);
416 struct ProfileDataSection
421 CORBBTPROF_TOKEN_INFO *pTable;
425 ProfileDataSection m_profileDataSections[SectionFormatCount];
427 DWORD m_profileDataNumRuns;
429 CorInfoRegionKind m_currentRegionKind;
431 BOOL IsAssemblyBeingCompiled(CORINFO_MODULE_HANDLE module) {
432 return ((module == m_hModule) ||
433 (m_zapper->m_pEECompileInfo->GetModuleAssembly(module) == m_zapper->m_hAssembly));
436 class ZapMethodTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapMethodHeader *> >
439 typedef CORINFO_METHOD_HANDLE key_t;
441 static key_t GetKey(element_t e)
443 LIMITED_METHOD_CONTRACT;
444 return e->GetHandle();
446 static BOOL Equals(key_t k1, key_t k2)
448 LIMITED_METHOD_CONTRACT;
451 static count_t Hash(key_t k)
453 LIMITED_METHOD_CONTRACT;
454 return (count_t)(size_t)k;
458 typedef SHash<ZapMethodTraits> ZapMethodHashTable;
460 ZapMethodHashTable m_CompiledMethods;
462 SArray<ZapMethodHeader *> m_MethodCompilationOrder;
464 SArray<ZapGCInfo *> m_PrioritizedGCInfo;
466 #ifndef FEATURE_FULL_NGEN
467 class MethodCodeTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapMethodHeader *> >
470 typedef ZapMethodHeader * key_t;
472 static FORCEINLINE key_t GetKey(element_t e)
474 LIMITED_METHOD_CONTRACT;
478 static BOOL Equals(key_t k1, key_t k2);
479 static COUNT_T Hash(key_t k);
481 static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; }
482 static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
485 typedef SHash <MethodCodeTraits> ZapMethodCodeHashTable;
487 ZapMethodCodeHashTable m_CodeDeduplicator;
488 #endif // FEATURE_FULL_NGEN
490 struct ClassLayoutOrderEntry
492 CORINFO_CLASS_HANDLE m_cls;
495 ClassLayoutOrderEntry()
496 : m_cls(0), m_order(0)
500 ClassLayoutOrderEntry(CORINFO_CLASS_HANDLE cls, unsigned order)
501 : m_cls(cls), m_order(order)
506 class ClassLayoutOrderTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ClassLayoutOrderEntry> >
509 typedef CORINFO_CLASS_HANDLE key_t;
511 static key_t GetKey(element_t e)
513 LIMITED_METHOD_CONTRACT;
516 static BOOL Equals(key_t k1, key_t k2)
518 LIMITED_METHOD_CONTRACT;
521 static count_t Hash(key_t k)
523 LIMITED_METHOD_CONTRACT;
524 return (count_t)(size_t)k;
526 static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(0,0); }
527 static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_cls == 0; }
530 typedef SHash<ClassLayoutOrderTraits> ClassLayoutOrderHashTable;
532 ClassLayoutOrderHashTable m_ClassLayoutOrder;
534 // See ComputeClassLayoutOrder for an explanation of these flags
535 #define UNSEEN_CLASS_FLAG (0x80000000)
536 #define METHOD_INDEX_FLAG (0x40000000)
538 // The class layout order needs to be initialized with the first index
539 // in m_MethodCompilationOrder of a method in the given class.
540 inline void InitializeClassLayoutOrder(CORINFO_CLASS_HANDLE cls, unsigned order)
544 if (!m_ClassLayoutOrder.LookupPtr(cls))
546 ClassLayoutOrderEntry entry(cls, order | UNSEEN_CLASS_FLAG | METHOD_INDEX_FLAG);
547 m_ClassLayoutOrder.Add(entry);
552 inline unsigned LookupClassLayoutOrder(CORINFO_CLASS_HANDLE cls)
556 const ClassLayoutOrderEntry *pEntry = m_ClassLayoutOrder.LookupPtr(cls);
557 _ASSERTE(!pEntry || pEntry->m_order != 0);
559 return pEntry ? pEntry->m_order : 0;
565 // The image layout algorithm
575 ZapVirtualSection * GetCodeSection(CodeType codeType);
576 ZapVirtualSection * GetRuntimeFunctionSection(CodeType codeType);
577 ZapVirtualSection * GetCodeMethodDescSection(CodeType codeType);
578 ZapVirtualSection * GetUnwindInfoLookupSection(CodeType codeType);
580 #if defined(WIN64EXCEPTIONS)
581 ZapVirtualSection * GetUnwindDataSection(CodeType codeType);
584 void GetCodeCompilationRange(CodeType codeType, COUNT_T * start, COUNT_T * end);
586 void OutputCode(CodeType codeType);
587 void OutputCodeInfo(CodeType codeType);
591 void OutputDebugInfo();
592 void OutputProfileData();
594 void OutputEntrypointsTableForReadyToRun();
595 void OutputDebugInfoForReadyToRun();
596 void OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport);
597 void OutputInliningTableForReadyToRun();
598 void OutputProfileDataForReadyToRun();
600 void CopyDebugDirEntry();
601 void CopyWin32VersionResource();
603 void OutputManifestMetadata();
606 // Assign RVAs to all ZapNodes
609 HANDLE GenerateFile(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
611 void PrintStats(LPCWSTR wszOutputFileName);
613 bool m_fHasClassLayoutOrder;
615 void ComputeClassLayoutOrder();
616 void SortUnprofiledMethodsByClassLayoutOrder();
618 HRESULT GetPdbFileNameFromModuleFilePath(__in_z const wchar_t *pwszModuleFilePath,
619 __out_ecount(dwPdbFileNameBufferSize) char * pwszPdbFileName,
620 DWORD dwPdbFileNameBufferSize);
623 ZapImage(Zapper *zapper);
626 // ----------------------------------------------------------------------------------------------------------
628 // Utility function for converting ZapWriter * to ZapImage *. This cast should not be done directly by the code
629 // so that the relationship between ZapWriter and ZapImage is abstracted away.
631 static ZapImage * GetImage(ZapWriter * pZapWriter)
633 return (ZapImage *)pZapWriter;
636 // ----------------------------------------------------------------------------------------------------------
638 // Add relocation record. This method is meant to be called from the Save method of custom ZapNodes right
639 // before the given datastructure is written into the native image.
642 // pSrc - the datastructure being written
643 // offset - offset of the relocation within the datastructure
644 // pTarget - target of the relocation
645 // targetOffset - adjusment of the target (usually 0)
646 // type - relocation type (IMAGE_REL_BASED_XXX enum, note that we have private additions to this enum:
647 // IMAGE_REL_BASED_PTR - architecture specific reloc of virtual address
648 // IMAGE_REL_BASED_ABSOLUTE_TAGGED - absolute stored in the middle 30-bits, used for fixups.
649 // IMAGE_REL_BASED_RELPTR - pointer stored as address relative delta
650 // IMAGE_REL_BASED_RELPTR32 - pointer stored as address relative 32-bit delta
652 void WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type);
654 void Open(CORINFO_MODULE_HANDLE hModule, IMetaDataAssemblyEmit *pEmit);
656 void InitializeSections();
657 void InitializeSectionsForReadyToRun();
659 // Wrapper of ZapWriter::NewVirtualSection that sets sectionType
660 ZapVirtualSection * NewVirtualSection(ZapPhysicalSection * pPhysicalSection, DWORD sectionType /* ZapVirtualSectionType */, DWORD dwAlignment = 16, ZapVirtualSection * pInsertAfter = NULL)
662 ZapVirtualSection * pSection = ZapWriter::NewVirtualSection(pPhysicalSection, dwAlignment, pInsertAfter);
663 pSection->SetSectionType(sectionType);
667 void AllocateVirtualSections();
669 HANDLE SaveImage(LPCWSTR wszOutputFileName, LPCWSTR wszDllPath, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
674 void SetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo);
675 void SetDependencies(CORCOMPILE_DEPENDENCY *pDependencies, DWORD cDependencies);
676 void SetPdbFileName(const SString &strFileName);
678 #ifdef WIN64EXCEPTIONS
679 void SetRuntimeFunctionsDirectoryEntry();
682 void SaveCorHeader();
683 void SaveNativeHeader();
684 void SaveCodeManagerEntry();
688 ZapMethodHeader * GetCompiledMethod(CORINFO_METHOD_HANDLE handle)
690 return m_CompiledMethods.Lookup(handle);
693 static void __stdcall TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags);
695 BOOL IsVTableGapMethod(mdMethodDef md);
697 CompileStatus TryCompileMethodDef(mdMethodDef md, unsigned methodProfilingDataFlags);
698 CompileStatus TryCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle, unsigned methodProfilingDataFlags);
699 CompileStatus TryCompileMethodWorker(CORINFO_METHOD_HANDLE handle, mdMethodDef md, unsigned methodProfilingDataFlags);
701 BOOL ShouldCompileMethodDef(mdMethodDef md);
702 BOOL ShouldCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle);
704 bool canIntraModuleDirectCall(CORINFO_METHOD_HANDLE callerFtn,
705 CORINFO_METHOD_HANDLE targetFtn,
706 CorInfoIndirectCallReason *pReason = NULL,
707 CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY);
709 CORINFO_MODULE_HANDLE GetModuleHandle()
714 IMetaDataAssemblyEmit * GetAssemblyEmit()
716 return m_pAssemblyEmit;
719 ZapWrapperTable * GetWrappers()
724 ZapImportTable * GetImportTable()
726 return m_pImportTable;
729 ZapImportSectionsTable * GetImportSectionsTable()
731 return m_pImportSectionsTable;
734 ZapNode * GetEEInfoTable()
736 return m_pEEInfoTable;
739 ZapReadyToRunHeader * GetReadyToRunHeader()
741 _ASSERTE(IsReadyToRunCompilation());
742 return (ZapReadyToRunHeader *)m_pNativeHeader;
745 ZapNode * GetInnerPtr(ZapNode * pNode, SSIZE_T offset);
747 CorInfoRegionKind GetCurrentRegionKind()
749 return m_currentRegionKind;
753 // Called from ZapImportTable::PlaceBlob
754 // to determine wheather to place the new signature Blob
755 // into the HotImports or the ColdImports section.
757 // The Assert will fire if BeginRegion was not called
758 // to setup the region
760 bool IsCurrentCodeRegionHot()
762 if (GetCurrentRegionKind() == CORINFO_REGION_HOT)
766 else if (GetCurrentRegionKind() == CORINFO_REGION_COLD)
770 _ASSERTE(!"unsupported RegionKind");
775 // Marks the start of a region where we want to place any
776 // new signature Blobs into the Hot/Cold region
778 void BeginRegion(CorInfoRegionKind regionKind)
780 _ASSERTE(GetCurrentRegionKind() == CORINFO_REGION_NONE);
781 m_currentRegionKind = regionKind;
785 // Marks the end of a region and we no longer expect to
786 // need any new signature Blobs
788 void EndRegion(CorInfoRegionKind regionKind)
790 _ASSERTE(GetCurrentRegionKind() == regionKind);
791 m_currentRegionKind = CORINFO_REGION_NONE;
794 ICorCompilationDomain * GetDomain()
796 return m_zapper->m_pDomain;
799 ICorDynamicInfo * GetJitInfo()
801 return m_zapper->m_pEEJitInfo;
804 ICorCompileInfo * GetCompileInfo()
806 return m_zapper->m_pEECompileInfo;
809 ZapperOptions * GetZapperOptions()
811 return m_zapper->m_pOpt;
814 ZapNode * GetHelperThunkIfExists(CorInfoHelpFunc ftnNum)
816 return m_pHelperThunks[ftnNum];
819 ZapNode * GetHelperThunk(CorInfoHelpFunc ftnNum);
821 BOOL HasClassLayoutOrder()
823 return m_fHasClassLayoutOrder;
826 HRESULT PrintTokenDescription(CorZapLogLevel level, mdToken token);
828 // ICorCompileDataStore
831 virtual ZapImage * GetZapImage();
832 void Error(mdToken token, HRESULT error, UINT resID, LPCWSTR message);
834 // Returns virtual section for EE datastructures
835 ZapVirtualSection * GetSection(CorCompileSection section)
837 return m_pPreloadSections[section];
840 HRESULT LocateProfileData();
841 HRESULT parseProfileData ();
842 HRESULT convertProfileDataFromV1();
843 void RehydrateBasicBlockSection();
844 void RehydrateTokenSection(int sectionFormat, unsigned int flagTable[255]);
845 void RehydrateBlobStream();
846 HRESULT RehydrateProfileData();
847 HRESULT hashBBProfileData ();
848 void hashBBUpdateFlagsAndCompileResult(mdToken token, unsigned methodProfilingDataFlags, CompileStatus compileResult);
850 void LoadProfileData();
851 CorProfileData * NewProfileData();
852 CorProfileData * GetProfileData();
853 bool CanConvertIbcData();
855 CompileStatus CompileProfileDataWorker(mdToken token, unsigned methodProfilingDataFlags);
857 void ProfileDisableInlining();
858 void CompileHotRegion();
859 void CompileColdRegion();
860 void PlaceMethodIL();
867 unsigned int m_length;
868 unsigned int m_currentPosition;
872 // Make sure that the buffer is at least newLength bytes long;
873 // expand it if necessary.
874 void RequireLength(unsigned int newLength)
876 if (newLength <= m_length)
881 if (newLength < (m_length * 3) / 2)
883 newLength = (m_length * 3) / 2;
886 char *newBuffer = new (m_heap) char[newLength];
888 memcpy(newBuffer, m_buffer, m_length);
890 m_length = newLength;
891 m_buffer = newBuffer;
895 BinaryWriter(unsigned int initialLength, ZapHeap *heap)
898 m_length = initialLength;
899 m_buffer = new (m_heap) char[initialLength];
900 m_currentPosition = 0;
903 template <typename T>
904 void WriteAt(unsigned int position, const T &v)
906 RequireLength(position + sizeof(T));
908 *(T *)(m_buffer + position) = v;
911 template <typename T>
912 void Write(const T &v)
914 WriteAt<T>(m_currentPosition, v);
915 m_currentPosition += sizeof(T);
918 void Write(const char *data, unsigned int length)
920 RequireLength(m_currentPosition + length);
922 memcpy(m_buffer + m_currentPosition, data, length);
923 m_currentPosition += length;
928 return (BYTE *)m_buffer;
931 unsigned int GetWrittenSize()
933 return m_currentPosition;
940 ProfileReader(void *buffer, ULONG length)
942 profileBuffer = (char *) buffer;
949 if (pos <= bufferSize)
956 _ASSERTE(!"ProfileReader: attempt to seek out of bounds");
961 void *Read(ULONG size)
963 ULONG oldPos = currentPos;
965 if (!Seek(currentPos + size))
970 return (void *)(profileBuffer + oldPos);
973 template <typename T> T Read()
975 T* pResult = (T*)Read(sizeof(T));
985 // Read an integer a la BinaryReader.Read7BitEncodedInt.
986 unsigned int Read7BitEncodedInt()
988 unsigned int result = 0;
990 unsigned char current = 0x80;
992 while ((currentPos < bufferSize) &&
995 current = profileBuffer[currentPos++];
996 result |= (current & 0x7f) << shift;
999 if (!(current & 0x80))
1005 _ASSERTE(!"Improperly encoded value");
1009 // Read a token given a 'memory' value--the last token of this type read
1010 // from the stream. The encoding takes advantage of the fact that two
1011 // adjacent tokens in the file are usually of the same type, and therefore
1012 // share a high byte. With the high byte removed the rest of the token can
1013 // be encoded more efficiently.
1014 mdToken ReadTokenWithMemory(mdToken &memory)
1019 current = Read7BitEncodedInt();
1021 unsigned char highByte = ((current >> 24) & 0xff);
1025 result = current | (memory & 0xff000000);
1027 else if (highByte == 0xff)
1029 result = current & 0x00ffffff;
1041 // Read a 32-bit flag value using a lookup table built while processing the
1042 // file. Flag values are represented by a one-byte index. If the index
1043 // hasn't occurred before in the file, it is followed by the four-byte flag
1044 // value it represents. The index 255 is used as an escape code--it is
1045 // always followed by a flag value.
1046 // flagTable must have 255 entries and they must all start as 0xFFFFFFFF.
1047 unsigned int ReadFlagWithLookup(unsigned int flagTable[255])
1049 unsigned char index;
1052 index = Read<unsigned char>();
1054 if ((index < 255) && (flagTable[index] != 0xffffffff))
1056 return flagTable[index];
1059 flags = Read<unsigned int>();
1063 flagTable[index] = flags;
1069 ULONG GetCurrentPos()
1071 _ASSERTE(currentPos <= bufferSize);
1076 char *profileBuffer;
1085 char path[MAX_LONGPATH];
1089 if (!profileReader.Seek(pos)) return E_FAIL;
1091 #define READ_SIZE(dst,type,size) \
1092 dst = (type *) profileReader.Read(size); \
1093 if (!dst) return E_FAIL;
1095 #define READ(dst,type) \
1096 READ_SIZE(dst,type,sizeof(type))
1098 #endif // __ZAPIMAGE_H__