diff options
author | dotnet-bot <dotnet-bot@microsoft.com> | 2015-01-30 14:14:42 -0800 |
---|---|---|
committer | dotnet-bot <dotnet-bot@microsoft.com> | 2015-01-30 14:14:42 -0800 |
commit | ef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch) | |
tree | dee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/zap/zapcode.h | |
download | coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2 coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip |
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/zap/zapcode.h')
-rw-r--r-- | src/zap/zapcode.h | 1128 |
1 files changed, 1128 insertions, 0 deletions
diff --git a/src/zap/zapcode.h b/src/zap/zapcode.h new file mode 100644 index 0000000000..a566beaddb --- /dev/null +++ b/src/zap/zapcode.h @@ -0,0 +1,1128 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// +// ZapCode.h +// + +// +// ZapNodes for everything directly related to zapping of native code +// +// code:ZapMethodHeader +// code:ZapMethodEntryPoint +// code:ZapMethodEntryPointTable +// code:ZapDebugInfo +// code:ZapProfileData +// code:ZapHelperTable +// code:ZapGCInfoTable + + +// +// ====================================================================================== + +#ifndef __ZAPCODE_H__ +#define __ZAPCODE_H__ + +// Forward declarations + +class ZapBlobWithRelocs; + +#ifdef REDHAWK +typedef ZapNode ZapGCInfo; +#else +#if defined(WIN64EXCEPTIONS) +class ZapGCInfo; +#else +typedef ZapBlob ZapGCInfo; +#endif +#endif // REDHAWK + +typedef ZapBlob ZapDebugInfo; +typedef ZapBlob ZapFixupInfo; +#ifdef REDHAWK +typedef ZapBlobWithRelocs ZapExceptionInfo; +#else +typedef ZapBlob ZapExceptionInfo; +#endif + +class ZapUnwindInfo; + +class ZapImport; + +class ZapInfo; + +class ZapGCRefMapTable; + +//--------------------------------------------------------------------------------------- +// +// ZapMethodHeader is the main node that all information about the compiled code is hanging from +// +class ZapMethodHeader : public ZapNode +{ + // All other kinds of method headers are tightly coupled with the main method header + friend class ZapProfileData; + friend class ZapCodeMethodDescs; + friend class ZapColdCodeMap; + + friend class MethodCodeComparer; + + friend class ZapImage; + friend class ZapInfo; + + CORINFO_METHOD_HANDLE m_handle; + CORINFO_CLASS_HANDLE m_classHandle; +#ifdef MDIL + mdMethodDef m_token; +#endif + +#ifdef BINDER + ZapNode * m_pMethodDesc; + ZapNode * m_pEntryPoint; // either the ZapBlob representing the precode + // or m_pCode (if the method can be called directly) +#endif // BINDER + + ZapBlobWithRelocs * m_pCode; + ZapBlobWithRelocs * m_pColdCode; // May be NULL + + ZapUnwindInfo * m_pUnwindInfo; + ZapUnwindInfo * m_pColdUnwindInfo; // May be NULL + +#ifdef WIN64EXCEPTIONS + ZapUnwindInfo * m_pUnwindInfoFragments; // Linked list of all unwind info fragments +#endif + + ZapBlobWithRelocs * m_pROData; // May be NULL + + ZapBlobWithRelocs * m_pProfileData; // May be NULL + + ZapGCInfo * m_pGCInfo; + ZapDebugInfo * m_pDebugInfo; + + union // May be NULL + { + ZapImport ** m_pFixupList; // Valid before place phase + ZapFixupInfo * m_pFixupInfo; // Valid after place phase + }; + + ZapExceptionInfo * m_pExceptionInfo; // May be NULL + + unsigned m_ProfilingDataFlags; + + unsigned m_compilationOrder; + unsigned m_cachedLayoutOrder; + + DWORD m_methodIndex; + + ZapMethodHeader() + { + } + +public: + CORINFO_METHOD_HANDLE GetHandle() + { + return m_handle; + } + + CORINFO_CLASS_HANDLE GetClassHandle() + { + return m_classHandle; + } + + DWORD GetMethodIndex() + { + return m_methodIndex; + } + +#ifdef MDIL + mdMethodDef GetToken() + { + return m_token; + } +#endif + + ZapBlobWithRelocs * GetCode() + { + return m_pCode; + } + + ZapBlobWithRelocs * GetColdCode() + { + return m_pColdCode; + } + + BOOL HasFixups() + { + return m_pFixupList != NULL; + } + + ZapNode * GetFixupList() + { + return m_pFixupInfo; + } + + ZapDebugInfo * GetDebugInfo() + { + return m_pDebugInfo; + } + + unsigned GetCompilationOrder() + { + return m_compilationOrder; + } + + unsigned GetCachedLayoutOrder() + { + return m_cachedLayoutOrder; + } + virtual ZapNodeType GetType() + { + return ZapNodeType_MethodHeader; + } + +#ifdef BINDER + void SetEntryPoint(ZapNode * pEntryPoint) + { + m_pEntryPoint = pEntryPoint; + } + + ZapNode *GetEntryPoint() + { + return m_pEntryPoint; + } + + bool HasMethodDesc() + { + return m_pMethodDesc != NULL; + } + + ZapNode *GetMethodDesc() + { + _ASSERTE(m_pMethodDesc != NULL); + return m_pMethodDesc; + } + + void SetMethodDesc(ZapNode *pMethodDesc) + { + _ASSERTE(m_pMethodDesc == NULL); + m_pMethodDesc = pMethodDesc; + _ASSERTE(m_pMethodDesc != NULL); + } +#endif // BINDER + + // Iterate over as many of the methods called by this method + // as are easy to determine. Currently this is implemented + // by walking the Reloc list and so is only as complete as + // the current state of the Relocs. Note that the implementation + // ignores virtual calls and calls in the cold code section. + class PartialTargetMethodIterator + { + public: + PartialTargetMethodIterator(ZapMethodHeader* pMethod) + : m_pMethod(pMethod) + { + ZapBlobWithRelocs * pCode = pMethod->GetCode(); + m_pCurReloc = pCode ? pCode->GetRelocs() : NULL; + } + + BOOL GetNext(CORINFO_METHOD_HANDLE *pHnd); + + private: + ZapMethodHeader* m_pMethod; + ZapReloc* m_pCurReloc; + }; + +}; + +#ifdef _TARGET_ARM_ +// Avoid ARM hazard due to QualComm Krait processor bug. +#define ARM_HAZARD_AVOIDANCE +#endif + +#if defined(_TARGET_X86_) || defined(ARM_HAZARD_AVOIDANCE) +class ZapCodeBlob : public ZapBlobWithRelocs +{ +protected: + ZapCodeBlob(SIZE_T cbSize) + : ZapBlobWithRelocs(cbSize) + { + } + +#if defined(TARGET_THUMB2) && defined(BINDER) + virtual BOOL IsThumb2Code() + { + return TRUE; + } +#endif + +public: + static ZapCodeBlob * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment); + + virtual DWORD ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos); +}; +#else +typedef ZapBlobWithRelocs ZapCodeBlob; +#endif + +class ZapCodeMethodDescs : public ZapNode +{ + COUNT_T m_iStartMethod; + COUNT_T m_iEndMethod; + COUNT_T m_nUnwindInfos; + +public: + ZapCodeMethodDescs(COUNT_T startMethod, COUNT_T endMethod, COUNT_T nUnwindInfos) + : m_iStartMethod(startMethod), m_iEndMethod(endMethod), m_nUnwindInfos(nUnwindInfos) + { + } + + virtual UINT GetAligment() + { + return sizeof(DWORD); + } + + virtual DWORD GetSize() + { + return m_nUnwindInfos * sizeof(DWORD); + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_CodeManagerMap; + } + + virtual void Save(ZapWriter * pZapWriter); +}; + +//--------------------------------------------------------------------------------------- +// +// ZapMethodEntryPoint is special type of placeholder. Unlike normal placeholder, it +// carries extra CORINFO_ACCESS_FLAGS that is used to opt into the direct call even +// when it would not be otherwise possible. +// +class ZapMethodEntryPoint : public ZapNode +{ + CORINFO_METHOD_HANDLE m_handle; // Target method being called + BYTE m_accessFlags; // CORINFO_ACCESS_FLAGS + BYTE m_fUsed; // Entrypoint is used - needs to be resolved + +#ifdef CLR_STANDALONE_BINDER + ZapNode *m_pEntryPoint; // only used for abstract methods to remember the precode +#endif // CLR_STANDALONE_BINDER + +public: + ZapMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) + : m_handle(handle), m_accessFlags(static_cast<BYTE>(accessFlags)) + { + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_MethodEntryPoint; + } + + CORINFO_METHOD_HANDLE GetHandle() + { + return m_handle; + } + + CORINFO_ACCESS_FLAGS GetAccessFlags() + { + return (CORINFO_ACCESS_FLAGS)m_accessFlags; + } + + void SetIsUsed() + { + m_fUsed = true; + } + + BOOL IsUsed() + { + return m_fUsed; + } + + void Resolve(ZapImage * pImage); +#ifdef CLR_STANDALONE_BINDER + void SetEntryPoint(ZapNode *entryPoint) + { + m_pEntryPoint = entryPoint; // only used for abstract methods to remember the precode + } +#endif // CLR_STANDALONE_BINDER + +#if defined(TARGET_THUMB2) && defined(BINDER) + virtual BOOL IsThumb2Code() + { + return TRUE; + } +#endif +}; + +class ZapMethodEntryPointTable +{ + struct MethodEntryPointKey + { + MethodEntryPointKey(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) + : m_handle(handle), m_accessFlags(accessFlags) + { + } + + CORINFO_METHOD_HANDLE m_handle; // Target method being called + CORINFO_ACCESS_FLAGS m_accessFlags; + }; + + class MethodEntryPointTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapMethodEntryPoint *> > + { + public: + typedef MethodEntryPointKey key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return MethodEntryPointKey(e->GetHandle(), e->GetAccessFlags()); + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return (k1.m_handle == k2.m_handle) && (k1.m_accessFlags == k2.m_accessFlags); + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + return (count_t)(size_t)k.m_handle ^ (count_t)k.m_accessFlags; + } + + static const element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } + static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } + }; + + typedef SHash< MethodEntryPointTraits > MethodEntryPointTable; + + MethodEntryPointTable m_entries; + ZapImage * m_pImage; + +public: + ZapMethodEntryPointTable(ZapImage * pImage) + : m_pImage(pImage) + { + } + + void Preallocate(COUNT_T cbILImage) + { + PREALLOCATE_HASHTABLE(ZapMethodEntryPointTable::m_entries, 0.0018, cbILImage); + } + + ZapMethodEntryPoint * GetMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags); + + ZapNode * CanDirectCall(ZapMethodEntryPoint * pMethodEntryPoint, ZapMethodHeader * pCaller); + + void Resolve(); +}; + +//--------------------------------------------------------------------------------------- +// +// Zapping of unwind info +// +class ZapUnwindInfo : public ZapNode +{ + ZapNode * m_pCode; + + DWORD m_dwStartOffset; + DWORD m_dwEndOffset; + + ZapNode * m_pUnwindData; + +#if defined(TARGET_THUMB2) && defined(BINDER) + DWORD m_packedUnwindData; +#endif + + + ZapUnwindInfo * m_pNextFragment; + +public: + ZapUnwindInfo(ZapNode * pCode, DWORD dwStartOffset, DWORD dwEndOffset, ZapNode * pUnwindData = NULL) + : m_pCode(pCode), + m_dwStartOffset(dwStartOffset), + m_dwEndOffset(dwEndOffset), +#if defined(TARGET_THUMB2) && defined(BINDER) + m_packedUnwindData(0), +#endif + m_pUnwindData(pUnwindData) + { + } + +#if defined(TARGET_THUMB2) && defined(BINDER) + ZapUnwindInfo(ZapNode * pCode, DWORD dwStartOffset, DWORD dwEndOffset, DWORD packedUnwindData) + : m_pCode(pCode), + m_dwStartOffset(dwStartOffset), + m_dwEndOffset(dwEndOffset), + m_packedUnwindData(packedUnwindData), + m_pUnwindData(NULL) + { + } +#endif // TARGET_THUMB2 + + ZapNode * GetCode() + { + return m_pCode; + } + + DWORD GetStartOffset() + { + return m_dwStartOffset; + } + + DWORD GetEndOffset() + { + return m_dwEndOffset; + } + + DWORD GetStartAddress() + { + return m_pCode->GetRVA() + GetStartOffset(); + } + + DWORD GetEndAddress() + { + return m_pCode->GetRVA() + GetEndOffset(); + } + // Used to set unwind data lazily + void SetUnwindData(ZapNode * pUnwindData) + { + _ASSERTE(m_pUnwindData == NULL); + m_pUnwindData = pUnwindData; + } + + ZapNode * GetUnwindData() + { + return m_pUnwindData; + } + + void SetNextFragment(ZapUnwindInfo * pFragment) + { + _ASSERTE(m_pNextFragment == NULL); + m_pNextFragment = pFragment; + } + + ZapUnwindInfo * GetNextFragment() + { + return m_pNextFragment; + } + + virtual UINT GetAlignment() + { + return sizeof(ULONG); + } + + virtual DWORD GetSize() + { + return sizeof(RUNTIME_FUNCTION); + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_UnwindInfo; + } + + virtual void Save(ZapWriter * pZapWriter); + + static int __cdecl CompareUnwindInfo(const void * a, const void * b); +}; + +#ifdef WIN64EXCEPTIONS +//--------------------------------------------------------------------------------------- +// +// Zapping of unwind data +// +class ZapUnwindData : public ZapBlob +{ +public: + ZapUnwindData(SIZE_T cbSize) + : ZapBlob(cbSize) + { + } + + virtual UINT GetAlignment(); + + virtual DWORD GetSize(); + + virtual ZapNodeType GetType() + { + return ZapNodeType_UnwindData; + } + + BOOL IsFilterFunclet() + { + return GetType() == ZapNodeType_FilterFuncletUnwindData; + } + + ZapNode * GetPersonalityRoutine(ZapImage * pImage); + virtual void Save(ZapWriter * pZapWriter); + + static ZapUnwindData * NewUnwindData(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, BOOL fIsFilterFunclet); +}; + +class ZapFilterFuncletUnwindData : public ZapUnwindData +{ +public: + ZapFilterFuncletUnwindData(SIZE_T cbSize) + : ZapUnwindData(cbSize) + { + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_FilterFuncletUnwindData; + } +}; +class ZapUnwindDataTable +{ + ZapImage * m_pImage; + + struct ZapUnwindDataKey + { + ZapUnwindDataKey(PVOID pUnwindData, SIZE_T cbUnwindData, BOOL fIsFilterFunclet) + : m_unwindData(pUnwindData, cbUnwindData), m_fIsFilterFunclet(fIsFilterFunclet) + { + } + + ZapBlob::SHashKey m_unwindData; + BOOL m_fIsFilterFunclet; + }; + + class ZapUnwindDataTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapUnwindData *> > + { + public: + typedef ZapUnwindDataKey key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return ZapUnwindDataKey(e->GetData(), e->GetBlobSize(), e->IsFilterFunclet()); + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return ZapBlob::SHashTraits::Equals(k1.m_unwindData, k2.m_unwindData) && (k1.m_fIsFilterFunclet == k2.m_fIsFilterFunclet); + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + return ZapBlob::SHashTraits::Hash(k.m_unwindData) ^ k.m_fIsFilterFunclet; + } + + static const element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } + static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } + }; + // Hashtable with all unwind data blobs. If two methods have unwind data + // we store it just once. + SHash< ZapUnwindDataTraits > m_blobs; + +public: + ZapUnwindDataTable(ZapImage * pImage) + : m_pImage(pImage) + { + } + + void Preallocate(COUNT_T cbILImage) + { + PREALLOCATE_HASHTABLE(ZapUnwindDataTable::m_blobs, 0.0003, cbILImage); + } + + ZapUnwindData * GetUnwindData(PVOID pBlob, SIZE_T cbBlob, BOOL fIsFilterFunclet); +}; +#endif // WIN64EXCEPTIONS + + +//--------------------------------------------------------------------------------------- +// +// Zapping of GC info +// +#ifdef WIN64EXCEPTIONS +class ZapGCInfo : public ZapUnwindData +{ + DWORD m_cbGCInfo; + +public: + ZapGCInfo(SIZE_T cbGCInfo, SIZE_T cbUnwindInfo) + : ZapUnwindData(cbUnwindInfo), m_cbGCInfo((DWORD)cbGCInfo) + { + if (m_cbGCInfo > ZAPWRITER_MAX_SIZE) + ThrowHR(COR_E_OVERFLOW); + } + + virtual PBYTE GetData() + { + return (PBYTE)(this + 1); + } + + PBYTE GetGCInfo() + { + return GetData() + GetUnwindInfoSize(); + } + + DWORD GetGCInfoSize() + { + return m_cbGCInfo; + } + + PBYTE GetUnwindInfo() + { + return GetData(); + } + + DWORD GetUnwindInfoSize() + { + return GetBlobSize(); + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_UnwindDataAndGCInfo; + } + + virtual DWORD GetSize() + { + return ZapUnwindData::GetSize() + m_cbGCInfo; + } + + virtual void Save(ZapWriter * pZapWriter) + { + ZapUnwindData::Save(pZapWriter); + + pZapWriter->Write(GetGCInfo(), GetGCInfoSize()); + } + + static ZapGCInfo * NewGCInfo(ZapWriter * pWriter, PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo); +}; + +class ZapGCInfoTable +{ + ZapImage * m_pImage; + + struct GCInfoKey + { + GCInfoKey(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo) + : m_gcInfo(pGCInfo, cbGCInfo), m_unwindInfo(pUnwindInfo, cbUnwindInfo) + { + } + + ZapBlob::SHashKey m_gcInfo; + ZapBlob::SHashKey m_unwindInfo; + }; + + class GCInfoTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapGCInfo *> > + { + public: + typedef GCInfoKey key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return GCInfoKey(e->GetGCInfo(), e->GetGCInfoSize(), e->GetUnwindInfo(), e->GetUnwindInfoSize()); + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return ZapBlob::SHashTraits::Equals(k1.m_gcInfo, k2.m_gcInfo) && ZapBlob::SHashTraits::Equals(k1.m_unwindInfo, k2.m_unwindInfo); + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + return ZapBlob::SHashTraits::Hash(k.m_gcInfo) ^ ZapBlob::SHashTraits::Hash(k.m_unwindInfo); + } + + static const element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } + static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } + }; + + // Hashtable with all GC info blobs. If two methods have same GC info + // we store it just once. + SHash< GCInfoTraits > m_blobs; + +public: + ZapGCInfoTable(ZapImage * pImage) + : m_pImage(pImage) + { + } + + void Preallocate(COUNT_T cbILImage) + { + PREALLOCATE_HASHTABLE(ZapGCInfoTable::m_blobs, 0.0021, cbILImage); + } + + // Returns interned instance of the GC info blob + ZapGCInfo * GetGCInfo(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo); +}; +#else +class ZapGCInfoTable +{ + ZapImage * m_pImage; + + // Hashtable with all GC info blobs. If two methods have same GC info + // we store it just once. + SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; + +public: + ZapGCInfoTable(ZapImage * pImage) + : m_pImage(pImage) + { + } + + void Preallocate(COUNT_T cbILImage) + { + PREALLOCATE_HASHTABLE(ZapGCInfoTable::m_blobs, 0.0021, cbILImage); + } + + // Returns interned instance of the GC info blob + ZapGCInfo * GetGCInfo(PVOID pBlob, SIZE_T cbBlob); +}; +#endif + +//--------------------------------------------------------------------------------------- +// +// Zapping of debug info for native code +// +class ZapDebugInfoTable : public ZapNode +{ + COUNT_T m_nCount; + ZapNode ** m_pTable; + + ZapImage * m_pImage; + + // Hashtable with all debug info blobs. If two methods have same debug info + // we store it just once. + SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; + + class LabelledEntry : public ZapNode + { + public: + LabelledEntry * m_pNext; + ZapMethodHeader * m_pMethod; + + LabelledEntry(ZapMethodHeader * pMethod) + : m_pMethod(pMethod) + { + } + + virtual DWORD GetSize() + { + return sizeof(CORCOMPILE_DEBUG_LABELLED_ENTRY); + } + + virtual UINT GetAlignment() + { + return sizeof(DWORD); + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_DebugInfoLabelledEntry; + } + + virtual void Save(ZapWriter * pZapWriter); + }; + +public: + ZapDebugInfoTable(ZapImage * pImage) + : m_pImage(pImage) + { + } + + void Preallocate(COUNT_T cbILImage) + { + PREALLOCATE_HASHTABLE(ZapDebugInfoTable::m_blobs, 0.0024, cbILImage); + } + + // Returns interned instance of the debug info blob + ZapDebugInfo * GetDebugInfo(PVOID pBlob, SIZE_T cbBlob); + + void PrepareLayout(); + void PlaceDebugInfo(ZapMethodHeader * pMethod); + void FinishLayout(); + + virtual DWORD GetSize() + { + return m_nCount * sizeof(CORCOMPILE_DEBUG_RID_ENTRY); + } + + virtual UINT GetAlignment() + { + return sizeof(DWORD); + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_DebugInfoTable; + } + + virtual void Save(ZapWriter * pZapWriter); +}; + +#ifdef MDIL +class MdilDebugInfoTable +{ +public: + MdilDebugInfoTable(ZapImage *pImage) : m_pImage(pImage) { } + + class DebugInfo + { + COUNT_T m_offset; + COUNT_T m_cbSize; + const SArray<BYTE> *m_pBuf; + + public: + DebugInfo(COUNT_T offset, COUNT_T cbSize, const SArray<BYTE> *pBuf) : m_offset(offset), m_cbSize(cbSize), m_pBuf(pBuf) { } + COUNT_T GetOffset() const { return m_offset; } + COUNT_T GetBlobSize() const { return m_cbSize; } + const SArray<BYTE> *GetBuf() const { return m_pBuf; } + const BYTE *GetData() const { return &(*m_pBuf)[m_offset]; } + }; + + const DebugInfo *GetDebugInfo(COUNT_T offset, COUNT_T cbBlob, const SArray<BYTE> *pBuf); + +private: + class SHashTraits : public DefaultSHashTraits<DebugInfo*> + { + public: + typedef const element_t key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return e; + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + if (k1->GetBuf() != k2->GetBuf()) + return FALSE; + if (k1->GetBlobSize() != k2->GetBlobSize()) + return FALSE; + return memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) == 0; + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + count_t hash = 5381 + (count_t)(k->GetBlobSize() << 7); + + const BYTE *pbData = k->GetData(); + const BYTE *pbDataEnd = pbData + k->GetBlobSize(); + + for (/**/ ; pbData < pbDataEnd; pbData++) + { + hash = ((hash << 5) + hash) ^ *pbData; + } + return hash; + } + }; + + ZapImage * m_pImage; + SHash< NoRemoveSHashTraits < SHashTraits > > m_blobs; +}; +#endif // MDIL + +//--------------------------------------------------------------------------------------- +// +// Zapping of IBC profile data collection area +// +class ZapProfileData : public ZapNode +{ + ZapMethodHeader * m_pMethod; + ZapProfileData * m_pNext; + +public: + ZapProfileData(ZapMethodHeader * pMethod) + : m_pMethod(pMethod) + { + } + + void SetNext(ZapProfileData * pNext) + { + m_pNext = pNext; + } + + virtual DWORD GetSize() + { + return sizeof(CORCOMPILE_METHOD_PROFILE_LIST); + } + + virtual UINT GetAlignment() + { + return sizeof(TADDR); + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_ProfileData; + } + + virtual void Save(ZapWriter * pZapWriter); +}; + +// Zapping of ExceptionInfoTable +// ExceptionInfoTable is a lookup table that has 1 entry for each method with EH information. +// The table is sorted by method start address, so binary search is used during runtime to find +// the EH info for a given method given a method start address. +class ZapExceptionInfoLookupTable : public ZapNode +{ +private: + typedef struct + { + ZapNode* m_pCode; + ZapExceptionInfo* m_pExceptionInfo; + } ExceptionInfoEntry; + + SArray<ExceptionInfoEntry> m_exceptionInfoEntries; + ZapImage* m_pImage; +public: + ZapExceptionInfoLookupTable(ZapImage *pImage); + + void PlaceExceptionInfoEntry(ZapNode* pCode, ZapExceptionInfo* pExceptionInfo); + + virtual ZapNodeType GetType() + { + return ZapNodeType_ExceptionInfoTable; + } + virtual UINT GetAlignment() + { + return sizeof(TADDR); + } + virtual DWORD GetSize(); + virtual void Save(ZapWriter* pZapWriter); +}; + + +class ZapUnwindInfoLookupTable : public ZapNode +{ + +public: + ZapUnwindInfoLookupTable(ZapVirtualSection * pRuntimeFunctionSection, ZapNode * pCodeSection, DWORD totalCodeSize): + m_pRuntimeFunctionSection(pRuntimeFunctionSection), m_pCodeSection(pCodeSection), m_TotalCodeSize(totalCodeSize) + { + } + + COUNT_T GetNumEntries() + { + return m_TotalCodeSize/RUNTIME_FUNCTION_LOOKUP_STRIDE + 1; + } + virtual ZapNodeType GetType() + { + return ZapNodeType_UnwindInfoLookupTable; + } + virtual UINT GetAlignment() + { + return sizeof(DWORD); + } + virtual DWORD GetSize(); + virtual void Save(ZapWriter* pZapWriter); + +private: + ZapVirtualSection * m_pRuntimeFunctionSection; + ZapNode * m_pCodeSection; + DWORD m_TotalCodeSize; +}; + +class ZapColdCodeMap : public ZapNode +{ +public: + ZapColdCodeMap(ZapVirtualSection * pRuntimeFunctionSection): + m_pRuntimeFunctionSection (pRuntimeFunctionSection) + { + } + + virtual ZapNodeType GetType() + { + return ZapNodeType_ColdCodeMap; + } + virtual UINT GetAlignment() + { + return sizeof(DWORD); + } + virtual DWORD GetSize(); + virtual void Save(ZapWriter* pZapWriter); + +private: + ZapVirtualSection * m_pRuntimeFunctionSection; +}; + +// +//--------------------------------------------------------------------------------------- +// +// Jump thunk for JIT helper +// +#ifdef _DEBUG +const static PCSTR s_rgHelperNames[] = { +#define JITHELPER(code,pfnHelper,sig) #code , +#define DYNAMICJITHELPER(code,pfnHelper,sig) "<dynamic> " #code , +#include <jithelpers.h> +}; +#endif // _DEBUG + +class ZapHelperThunk : public ZapNode +{ + DWORD m_dwHelper; + +public: + ZapHelperThunk(DWORD dwHelper) + : m_dwHelper(dwHelper) + { +#ifdef _DEBUG + static_assert_no_msg(COUNTOF(s_rgHelperNames) == CORINFO_HELP_COUNT); + LOG((LF_ZAP, LL_INFO1000000, "Created ZapHelperThunk for helper %3d (%s)\n", + (USHORT)m_dwHelper, s_rgHelperNames[(USHORT)m_dwHelper])); +#endif // _DEBUG + } + + virtual DWORD GetSize(); + + virtual ZapNodeType GetType() + { + return ZapNodeType_HelperThunk; + } + + virtual void Save(ZapWriter * pZapWriter); + +#if defined(TARGET_THUMB2) && defined(BINDER) + virtual BOOL IsThumb2Code() + { + return TRUE; + } +#endif + +}; + +class ZapLazyHelperThunk : public ZapNode +{ + CorInfoHelpFunc m_dwHelper; + + ZapNode * m_pArg; + ZapNode * m_pTarget; + + DWORD SaveWorker(ZapWriter * pZapWriter); + +public: + ZapLazyHelperThunk(CorInfoHelpFunc dwHelper) + : m_dwHelper(dwHelper) + { + } + + void Place(ZapImage * pImage); + + virtual DWORD GetSize(); + + virtual ZapNodeType GetType() + { + return ZapNodeType_LazyHelperThunk; + } + + virtual void Save(ZapWriter * pZapWriter); + +#if defined(TARGET_THUMB2) && defined(BINDER) + virtual BOOL IsThumb2Code() + { + return TRUE; + } +#endif +}; + +#endif // __ZAPCODE_H__ |