summaryrefslogtreecommitdiff
path: root/src/zap/zapcode.h
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
committerdotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
commitef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch)
treedee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/zap/zapcode.h
downloadcoreclr-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.h1128
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__