| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | |
| 5 | // |
| 6 | // Hash table associated with each module that records for all types defined in that module the mapping |
| 7 | // between type name and token (or TypeHandle). |
| 8 | // |
| 9 | |
| 10 | #ifndef __CLASS_HASH_INCLUDED |
| 11 | #define __CLASS_HASH_INCLUDED |
| 12 | |
| 13 | #include "ngenhash.h" |
| 14 | |
| 15 | // The type of each entry in the hash. |
| 16 | typedef DPTR(struct EEClassHashEntry) PTR_EEClassHashEntry; |
| 17 | class EEClassHashTable; |
| 18 | typedef struct EEClassHashEntry |
| 19 | { |
| 20 | friend class EEClassHashTable; |
| 21 | #ifdef DACCESS_COMPILE |
| 22 | friend class NativeImageDumper; |
| 23 | #endif |
| 24 | |
| 25 | #ifdef _DEBUG |
| 26 | PTR_CUTF8 DebugKey[2]; // Name of the type |
| 27 | #endif // _DEBUG |
| 28 | |
| 29 | // Accessors for encloser (pointer to hash entry of enclosing type when this entry describes a nested |
| 30 | // type). You need to use the accessors since the reference is not encoded as a simple pointer anymore. |
| 31 | PTR_EEClassHashEntry GetEncloser(); |
| 32 | void SetEncloser(EEClassHashEntry *pEncloser) DAC_EMPTY(); |
| 33 | |
| 34 | // Bit masks for flags in the data field. <NICE>Ideally we'd abstract this encoding but that's too much |
| 35 | // code churn right now.</NICE> |
| 36 | #define EECLASSHASH_TYPEHANDLE_DISCR ((ULONG_PTR)(UINT)0x00000001) |
| 37 | #define EECLASSHASH_MDEXPORT_DISCR ((ULONG_PTR)(UINT)0x80000000) |
| 38 | #define EECLASSHASH_ALREADYSEEN ((ULONG_PTR)(UINT)0x40000000) |
| 39 | |
| 40 | // Accessors for the data field (TypeHandle or a token with EECLASSHASH_TYPEHANDLE_DISCR set and possibly |
| 41 | // some of the other flag bits above). The type handle is also encoded as a non-regular pointer, so use |
| 42 | // this accessor. |
| 43 | PTR_VOID GetData(); |
| 44 | void SetData(PTR_VOID data) DAC_EMPTY(); |
| 45 | |
| 46 | private: |
| 47 | PTR_VOID m_Data; // Either the token (if EECLASSHASH_TYPEHANDLE_DISCR), or the type handle encoded |
| 48 | // as a relative pointer |
| 49 | |
| 50 | NgenHashEntryRef<EEClassHashTable, EEClassHashEntry, 4> m_pEncloser; // If this entry is a for a nested |
| 51 | // class, this field stores a |
| 52 | // reference to the enclosing type |
| 53 | // (which must be in this same |
| 54 | // hash). The NgenHashEntryRef<> |
| 55 | // is required to abstract some |
| 56 | // complex logic required while |
| 57 | // ngen'ing such references. |
| 58 | } EEClassHashEntry_t; |
| 59 | |
| 60 | // The hash type itself. All common logic is provided by the NgenHashTable templated base class. See |
| 61 | // NgenHash.h for details. |
| 62 | typedef DPTR(class EEClassHashTable) PTR_EEClassHashTable; |
| 63 | class EEClassHashTable : public NgenHashTable<EEClassHashTable, EEClassHashEntry, 4> |
| 64 | { |
| 65 | #ifdef DACCESS_COMPILE |
| 66 | friend class NativeImageDumper; |
| 67 | #endif |
| 68 | |
| 69 | public: |
| 70 | // The LookupContext type we export to track GetValue/FindNextNestedClass enumerations is simply a rename |
| 71 | // of the base classes' hash value enumerator. |
| 72 | typedef NgenHashTable<EEClassHashTable, EEClassHashEntry, 4>::LookupContext LookupContext; |
| 73 | |
| 74 | static EEClassHashTable *Create(Module *pModule, DWORD dwNumBuckets, BOOL bCaseInsensitive, AllocMemTracker *pamTracker); |
| 75 | |
| 76 | //NOTICE: look at InsertValue() in ClassLoader, that may be the function you want to use. Use this only |
| 77 | // when you are sure you want to insert the value in 'this' table. This function does not deal |
| 78 | // with case (as often the class loader has to) |
| 79 | EEClassHashEntry_t *InsertValue(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID Data, EEClassHashEntry_t *pEncloser, AllocMemTracker *pamTracker); |
| 80 | EEClassHashEntry_t *InsertValueIfNotFound(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID *pData, EEClassHashEntry_t *pEncloser, BOOL IsNested, BOOL *pbFound, AllocMemTracker *pamTracker); |
| 81 | EEClassHashEntry_t *InsertValueUsingPreallocatedEntry(EEClassHashEntry_t *pStorageForNewEntry, LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID Data, EEClassHashEntry_t *pEncloser); |
| 82 | EEClassHashEntry_t *GetValue(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID *pData, BOOL IsNested, LookupContext *pContext); |
| 83 | EEClassHashEntry_t *GetValue(LPCUTF8 pszFullyQualifiedName, PTR_VOID *pData, BOOL IsNested, LookupContext *pContext); |
| 84 | EEClassHashEntry_t *GetValue(NameHandle* pName, PTR_VOID *pData, BOOL IsNested, LookupContext *pContext); |
| 85 | EEClassHashEntry_t *AllocNewEntry(AllocMemTracker *pamTracker); |
| 86 | EEClassHashTable *MakeCaseInsensitiveTable(Module *pModule, AllocMemTracker *pamTracker); |
| 87 | EEClassHashEntry_t *FindItem(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, BOOL IsNested, LookupContext *pContext); |
| 88 | EEClassHashEntry_t *FindNextNestedClass(NameHandle* pName, PTR_VOID *pData, LookupContext *pContext); |
| 89 | EEClassHashEntry_t *FindNextNestedClass(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID *pData, LookupContext *pContext); |
| 90 | EEClassHashEntry_t *FindNextNestedClass(LPCUTF8 pszFullyQualifiedName, PTR_VOID *pData, LookupContext *pContext); |
| 91 | |
| 92 | BOOL CompareKeys(PTR_EEClassHashEntry pEntry, LPCUTF8 * pKey2); |
| 93 | |
| 94 | static DWORD Hash(LPCUTF8 pszNamespace, LPCUTF8 pszClassName); |
| 95 | |
| 96 | class ConstructKeyCallback |
| 97 | { |
| 98 | public: |
| 99 | virtual void UseKeys(__in_ecount(2) LPUTF8 *Key) = 0; |
| 100 | }; |
| 101 | |
| 102 | static PTR_VOID CompressClassDef(mdToken cl /* either a TypeDef or ExportedType*/); |
| 103 | bool UncompressModuleAndClassDef(PTR_VOID Data, Loader::LoadFlag loadFlag, |
| 104 | Module **ppModule, mdTypeDef *pCL, |
| 105 | mdExportedType *pmdFoundExportedType); |
| 106 | VOID UncompressModuleAndNonExportClassDef(PTR_VOID Data, Module **ppModule, |
| 107 | mdTypeDef *pCL); |
| 108 | static mdToken UncompressModuleAndClassDef(PTR_VOID Data); |
| 109 | |
| 110 | #ifdef DACCESS_COMPILE |
| 111 | void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); |
| 112 | void EnumMemoryRegionsForEntry(EEClassHashEntry_t *pEntry, CLRDataEnumMemoryFlags flags); |
| 113 | #endif |
| 114 | |
| 115 | #if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE) |
| 116 | void Save(DataImage *pImage, CorProfileData *pProfileData); |
| 117 | void Fixup(DataImage *pImage); |
| 118 | |
| 119 | private: |
| 120 | friend class NgenHashTable<EEClassHashTable, EEClassHashEntry, 4>; |
| 121 | |
| 122 | void PrepareExportedTypesForSaving(DataImage *image); |
| 123 | |
| 124 | bool ShouldSave(DataImage *pImage, EEClassHashEntry_t *pEntry); |
| 125 | bool IsHotEntry(EEClassHashEntry_t *pEntry, CorProfileData *pProfileData); |
| 126 | bool SaveEntry(DataImage *pImage, CorProfileData *pProfileData, EEClassHashEntry_t *pOldEntry, EEClassHashEntry_t *pNewEntry, EntryMappingTable *pMap); |
| 127 | void FixupEntry(DataImage *pImage, EEClassHashEntry_t *pEntry, void *pFixupBase, DWORD cbFixupOffset); |
| 128 | #endif // FEATURE_PREJIT && !DACCESS_COMPILE |
| 129 | |
| 130 | private: |
| 131 | #ifndef DACCESS_COMPILE |
| 132 | EEClassHashTable(Module *pModule, LoaderHeap *pHeap, DWORD cInitialBuckets) : |
| 133 | NgenHashTable<EEClassHashTable, EEClassHashEntry, 4>(pModule, pHeap, cInitialBuckets) {} |
| 134 | #endif |
| 135 | |
| 136 | VOID ConstructKeyFromData(PTR_EEClassHashEntry pEntry, ConstructKeyCallback * pCallback); |
| 137 | |
| 138 | BOOL m_bCaseInsensitive; // Default is true FALSE unless we call MakeCaseInsensitiveTable |
| 139 | }; |
| 140 | |
| 141 | #endif // !__CLASS_HASH_INCLUDED |
| 142 | |