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/vm/dataimage.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/vm/dataimage.h')
-rw-r--r-- | src/vm/dataimage.h | 464 |
1 files changed, 464 insertions, 0 deletions
diff --git a/src/vm/dataimage.h b/src/vm/dataimage.h new file mode 100644 index 0000000000..1921a268f4 --- /dev/null +++ b/src/vm/dataimage.h @@ -0,0 +1,464 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + + + +#ifndef _DATAIMAGE_H_ +#define _DATAIMAGE_H_ + +#if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE) + +// All we really need is to pre-declare the PrecodeType enum, but g++ doesn't +// support enum pre-declaration, so we need to include the declaration itself. +/*#include "cgensys.h" // needed to include precode.h*/ +#include "precode.h" + +typedef BYTE ZapRelocationType; // IMAGE_REL_XXX enum + +// IMAGE_REL_BASED_PTR is architecture specific reloc of virtual address +#ifdef _WIN64 +#define IMAGE_REL_BASED_PTR IMAGE_REL_BASED_DIR64 +#else +#define IMAGE_REL_BASED_PTR IMAGE_REL_BASED_HIGHLOW +#endif + +// Special NGEN-specific relocation type for relative pointer (used to make NGen relocation section smaller) +#define IMAGE_REL_BASED_RELPTR 0x7D + +class CEEPreloader; + +class ZapImage; +class TypeHandleList; + +class ZapNode; +class ZapStoredStructure; + +class ZapHeap; +void *operator new(size_t size, ZapHeap * pZapHeap); +void *operator new[](size_t size, ZapHeap * pZapHeap); + +class InternedStructureTraits; +typedef SHash<InternedStructureTraits> InternedStructureHashTable; + +struct LookupMapBase; +class InlineTrackingMap; + +class DataImage +{ +public: + // + // As items are recorded for saving we note some information about the item + // to help guide later heuristics. + // + enum ItemKind + { + #define DEFINE_ITEM_KIND(id) id, + #include "dataimagesection.h" + + ITEM_COUNT, + }; + + Module *m_module; + CEEPreloader *m_preloader; + ZapImage * m_pZapImage; + + struct StructureEntry + { + const void * ptr; + ZapNode * pNode; + SSIZE_T offset; + }; + + class StructureTraits : public NoRemoveSHashTraits< DefaultSHashTraits<StructureEntry> > + { + public: + typedef const void * key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return e.ptr; + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return (k1 == k2); + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + return (count_t)(size_t)k; + } + + static const element_t Null() { LIMITED_METHOD_CONTRACT; StructureEntry e; e.ptr = NULL; return e; } + static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.ptr == NULL; } + }; + typedef SHash<StructureTraits> StructureHashTable; + + StructureHashTable m_structures; + const StructureEntry * m_pLastLookup; // Cached result of last lookup + + #define MAINTAIN_SAVE_ORDER (0xFFFFFFFF) + + struct SavedNodeEntry + { + ZapNode * pNode; + DWORD dwAssociatedOrder; + }; + + // These are added in save order, however after PlaceRemainingStructures they may have been + // rearranged based on the class layout order stored in the dwAssociatedOrder field. + SArray<SavedNodeEntry> m_structuresInOrder; + + void AddStructureInOrder(ZapNode *pNode, BOOL fMaintainSaveOrder = FALSE); + + struct FixupEntry + { + ZapRelocationType m_type; + DWORD m_offset; +#ifdef _DEBUG + DWORD m_ordinal; +#endif // _DEBUG + + ZapStoredStructure * m_pLocation; + ZapNode * m_pTargetNode; + }; + + SArray<FixupEntry> m_Fixups; + COUNT_T m_iCurrentFixup; + + void AppendFixup(FixupEntry entry) + { +#ifdef _DEBUG + static DWORD s_ordinal = 1; + entry.m_ordinal = s_ordinal++; +#endif // _DEBUG + m_Fixups.Append(entry); + } + + static int __cdecl fixupEntryCmp(const void* a_, const void* b_); + + void FixupSectionRange(SIZE_T offset, ZapNode * pNode); + void FixupSectionPtr(SIZE_T offset, ZapNode * pNode); + void FixupJumpStubPtr(SIZE_T offset, CorInfoHelpFunc ftnNum); + + void FixupModuleRVAs(); + + InternedStructureHashTable * m_pInternedStructures; + SetSHash<ZapNode *> m_reusedStructures; + + struct RvaInfoStructure + { + FieldDesc * pFD; + DWORD rva; + UINT size; + UINT align; + }; + + SArray<RvaInfoStructure> m_rvaInfoVector; + + static int __cdecl rvaInfoVectorEntryCmp(const void* a_, const void* b_); + + MapSHash<PVOID,PVOID> m_surrogates; + + // Often set while a class is being saved in order to associate + // stored structures with the class, and therefore its layout order. + // Note that it is a best guess and not always set. + MethodTable * m_pCurrentAssociatedMethodTable; + + struct MethodProfilingData + { + MethodDesc *pMD; + DWORD flags; + }; + + class MethodProfilingDataTraits : public NoRemoveSHashTraits< DefaultSHashTraits<MethodProfilingData> > + { + public: + typedef const MethodDesc * key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return e.pMD; + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return (k1 == k2); + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + return (count_t)(size_t)k; + } + + static const element_t Null() { LIMITED_METHOD_CONTRACT; MethodProfilingData e; e.pMD = NULL; e.flags = 0; return e; } + static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.pMD == NULL; } + }; + typedef SHash<MethodProfilingDataTraits> MethodProfilingDataHashTable; + + MethodProfilingDataHashTable m_methodProfilingData; + + // This is a hashmap from inlinee method to an array of inliner methods + // So it can answer question: "where did this method get inlined ?" + InlineTrackingMap *m_inlineTrackingMap; + + public: +#ifndef CLR_STANDALONE_BINDER + DataImage(Module *module, CEEPreloader *preloader); +#else + DataImage(Module *module, ZapImage *pZapImage); +#endif + ~DataImage(); + + void Preallocate(); + + void PreSave(); + void PostSave(); + + Module *GetModule() { LIMITED_METHOD_CONTRACT; return m_module; } + + DWORD GetMethodProfilingFlags(MethodDesc * pMD); + void SetMethodProfilingFlags(MethodDesc * pMD, DWORD flags); + + CEEPreloader *GetPreloader() { LIMITED_METHOD_CONTRACT; return m_preloader; } + + ZapHeap * GetHeap(); + + // + // Data is stored in the image store in three phases. + // + + // + // In the first phase, all objects are assigned locations in the + // data store. This is done by calling StoreStructure on all + // structures which are being stored into the image. + // + // This would typically done by methods on the objects themselves, + // each of which stores itself and any objects it references. + // Reference loops must be explicitly tested for using IsStored. + // (Each structure can be stored only once.) + // + // Note that StoreStructure makes no guarantees about layout order. + // If you want structures of a particular kind to be laid out in + // the order they are saved, use StoreStructureInOrder. + // + + inline ZapStoredStructure * StoreStructure(const void *data, SIZE_T size, + ItemKind kind, + int align = sizeof(TADDR)) + { + return StoreStructureHelper(data, size, kind, align, FALSE); + } + + inline ZapStoredStructure * StoreStructureInOrder(const void *data, SIZE_T size, + ItemKind kind, + int align = sizeof(TADDR)) + { + return StoreStructureHelper(data, size, kind, align, TRUE); + } + + ZapStoredStructure * StoreStructureHelper(const void *data, SIZE_T size, + ItemKind kind, + int align, + BOOL fMaintainSaveOrder); + + // Often set while a class is being saved in order to associate + // stored structures with the class, and therefore its layout order. + // Note that it is a best guess and not always set. + inline void BeginAssociatingStoredObjectsWithMethodTable(MethodTable *pMT) + { + m_pCurrentAssociatedMethodTable = pMT; + } + + inline void EndAssociatingStoredObjectsWithMethodTable() + { + m_pCurrentAssociatedMethodTable = NULL; + } + + // Bind pointer to the relative offset in ZapNode + void BindPointer(const void *p, ZapNode * pNode, SSIZE_T offset); + + void BindPointer(const void *p, ZapStoredStructure * pNode, SSIZE_T offset) + { + BindPointer(p, (ZapNode *)pNode, offset); + } + + void CopyData(ZapStoredStructure * pNode, const void * p, ULONG size); + void CopyDataToOffset(ZapStoredStructure * pNode, ULONG offset, const void * p, ULONG size); + + // + // In the second phase, data is arranged in the image by successive calls + // to PlaceMappedRange. Items are arranged using pointers to data structures in the + // original heap, or by giving a StoredStructure along with the original + // mapping. + // + + // Concrete mapped ranges are the ones that actually correspond to allocations + // of new space within the image. They should be placed first. We do not + // necessarily populate the space in the image (i.e. copy the data to the image) + // from the concrete range: for example the space associated with a + // combo structure gets filled by copying the data from the individual items + // that make up the parts of the combo structure. + // + // These can tolerate placing the same item multiple times + // PlaceInternedStructureForAddress allows a different section to be used depending on + // whether an interned structure actually had duplicates in this image. + // + void PlaceStructureForAddress(const void * data, CorCompileSection section); + void PlaceInternedStructureForAddress(const void * data, CorCompileSection sectionIfReused, CorCompileSection sectionIfSingleton); + + void FixupPointerField(PVOID p, SSIZE_T offset); + void FixupRelativePointerField(PVOID p, SSIZE_T offset); + + void FixupField(PVOID p, SSIZE_T offset, PVOID pTarget, SSIZE_T targetOffset = 0, ZapRelocationType type = IMAGE_REL_BASED_PTR); + + void FixupFieldToNode(PVOID p, SSIZE_T offset, ZapNode * pTarget, SSIZE_T targetOffset = 0, ZapRelocationType type = IMAGE_REL_BASED_PTR); + + void FixupFieldToNode(PVOID p, SSIZE_T offset, ZapStoredStructure * pTarget, SSIZE_T targetOffset = 0, ZapRelocationType type = IMAGE_REL_BASED_PTR) + { + return FixupFieldToNode(p, offset, (ZapNode *)pTarget, targetOffset, type); + } + + BOOL IsStored(const void *data) + { WRAPPER_NO_CONTRACT; return m_structures.LookupPtr(data) != NULL; } + + DWORD GetRVA(const void *data); + + void ZeroField(PVOID p, SSIZE_T offset, SIZE_T size); + void *GetImagePointer(ZapStoredStructure * pNode); + void *GetImagePointer(PVOID p, SSIZE_T offset = 0); + ZapNode * GetNodeForStructure(PVOID p, SSIZE_T * pOffset); + + void ZeroPointerField(PVOID p, SSIZE_T offset) + { WRAPPER_NO_CONTRACT; ZeroField(p, offset, sizeof(void*)); } + + + ZapStoredStructure * StoreInternedStructure(const void *data, ULONG size, + ItemKind kind, + int align = sizeof(TADDR)); + + void NoteReusedStructure(const void *data); + + void StoreRvaInfo(FieldDesc * pFD, + DWORD rva, + UINT size, + UINT align); + + void SaveRvaStructure(); + void FixupRvaStructure(); + + // Surrogates are used to reorganize the data before they are saved. RegisterSurrogate and LookupSurrogate + // maintains mapping from the original data to the reorganized data. + void RegisterSurrogate(PVOID ptr, PVOID surrogate); + PVOID LookupSurrogate(PVOID ptr); + + void PlaceRemainingStructures(); + + void FixupRVAs(); + + void SetRVAsForFields(IMetaDataEmit * pEmit); + + // Called when data contains a function address. The data store + // can return a fixed compiled code address if it is compiling + // code for the module. + ZapNode * GetCodeAddress(MethodDesc * method); + + // Returns TRUE if the method can be called directly without going through prestub + BOOL CanDirectCall(MethodDesc * method, CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY); + + // Returns the method fixup info if it has one, NULL if method has no fixup info + ZapNode * GetFixupList(MethodDesc * method); + + ZapNode * GetHelperThunk(CorInfoHelpFunc ftnNum); + + // pUniqueId is used to allocate unique cells for cases where we cannot use the shared cell. + ZapNode * GetTypeHandleImport(TypeHandle th, PVOID pUniqueId = NULL); + ZapNode * GetMethodHandleImport(MethodDesc * pMD); + ZapNode * GetFieldHandleImport(FieldDesc * pFD); + ZapNode * GetModuleHandleImport(Module * pModule); + DWORD GetModuleImportIndex(Module * pModule); + + ZapNode * GetExistingTypeHandleImport(TypeHandle th); + ZapNode * GetExistingMethodHandleImport(MethodDesc * pMD); + ZapNode * GetExistingFieldHandleImport(FieldDesc * pFD); + + ZapNode * GetVirtualImportThunk(MethodTable * pMT, MethodDesc * pMD, int slotNumber); + + ZapNode * GetGenericSignature(PVOID signature, BOOL fMethod); + + void SavePrecode(PVOID ptr, MethodDesc * pMD, PrecodeType t, ItemKind kind, BOOL fIsPrebound = FALSE); + + void StoreCompressedLayoutMap(LookupMapBase *pMap, ItemKind kind); + + // "Fixup" here means "save the pointer either as a poiter or indirection" + void FixupModulePointer(Module * pModule, PVOID p, SSIZE_T offset, ZapRelocationType type); + void FixupMethodTablePointer(MethodTable * pMT, PVOID p, SSIZE_T offset, ZapRelocationType type); + void FixupTypeHandlePointer(TypeHandle th, PVOID p, SSIZE_T offset, ZapRelocationType type); + void FixupMethodDescPointer(MethodDesc * pMD, PVOID p, SSIZE_T offset, ZapRelocationType type); + void FixupFieldDescPointer(FieldDesc * pFD, PVOID p, SSIZE_T offset, ZapRelocationType type); + +#ifndef CLR_STANDALONE_BINDER + void FixupModulePointer(PVOID p, FixupPointer<PTR_Module> * ppModule); +#else + void FixupModulePointer(PVOID p, FixupPointer<PTR_ClrModule> * ppModule); +#endif + void FixupMethodTablePointer(PVOID p, FixupPointer<PTR_MethodTable> * ppMT); + void FixupTypeHandlePointer(PVOID p, FixupPointer<TypeHandle> * pth); + void FixupMethodDescPointer(PVOID p, FixupPointer<PTR_MethodDesc> * ppMD); + void FixupFieldDescPointer(PVOID p, FixupPointer<PTR_FieldDesc> * ppFD); + +#ifndef CLR_STANDALONE_BINDER + void FixupModulePointer(PVOID p, RelativeFixupPointer<PTR_Module> * ppModule); +#else + void FixupModulePointer(PVOID p, RelativeFixupPointer<PTR_ClrModule> * ppModule); +#endif + void FixupMethodTablePointer(PVOID p, RelativeFixupPointer<PTR_MethodTable> * ppMT); + void FixupTypeHandlePointer(PVOID p, RelativeFixupPointer<TypeHandle> * pth); + void FixupMethodDescPointer(PVOID p, RelativeFixupPointer<PTR_MethodDesc> * ppMD); + void FixupFieldDescPointer(PVOID p, RelativeFixupPointer<PTR_FieldDesc> * ppFD); + + // "HardBind" here means "save a reference using a (relocatable) pointer, + // where the object we're referring to lives either in an external hard-bound DLL + // or in the image currently being saved" + // + BOOL CanHardBindToZapModule(Module *targetModule); + + void ReportInlining(CORINFO_METHOD_HANDLE inliner, CORINFO_METHOD_HANDLE inlinee); + InlineTrackingMap *GetInlineTrackingMap(); + +private: + BOOL CanEagerBindTo(Module *targetModule, Module *pPreferredZapModule, void *address); + +public: + // "EagerBind" here means "save a reference using pointer in the image currently being saved + // or indirection cell refering to to external DLL + BOOL CanEagerBindToTypeHandle(TypeHandle th, BOOL fRequirePrerestore = FALSE, TypeHandleList *pVisited = NULL); + BOOL CanEagerBindToMethodTable(MethodTable *pMT, BOOL fRequirePrerestore = FALSE, TypeHandleList *pVisited = NULL); + BOOL CanEagerBindToMethodDesc(MethodDesc *pMD, BOOL fRequirePrerestore = FALSE, TypeHandleList *pVisited = NULL); + BOOL CanEagerBindToFieldDesc(FieldDesc *pFD, BOOL fRequirePrerestore = FALSE, TypeHandleList *pVisited = NULL); + BOOL CanEagerBindToModule(Module *pModule); + + // These also check that the target object doesn't need a restore action + // upon reload. + BOOL CanPrerestoreEagerBindToTypeHandle(TypeHandle th, TypeHandleList *pVisited); + BOOL CanPrerestoreEagerBindToMethodTable(MethodTable *pMT, TypeHandleList *pVisited); + BOOL CanPrerestoreEagerBindToMethodDesc(MethodDesc *pMD, TypeHandleList *pVisited); + + void HardBindTypeHandlePointer(PVOID p, SSIZE_T offset); + + // This is obsolete in-place fixup that we should get rid of. For now, it is used for: + // - FnPtrTypeDescs. These should not be stored in NGen images at all. + // - stubs-as-il signatures. These should use tokens when stored in NGen image. + void FixupTypeHandlePointerInPlace(PVOID p, SSIZE_T offset, BOOL fForceFixup = FALSE); + + void BeginRegion(CorInfoRegionKind regionKind); + void EndRegion(CorInfoRegionKind regionKind); +}; + +#endif // FEATURE_PREJIT && !DACCESS_COMPILE + +#endif // _DATAIMAGE_H_ |