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.
16typedef DPTR(struct EEClassHashEntry) PTR_EEClassHashEntry;
17class EEClassHashTable;
18typedef 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
46private:
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.
62typedef DPTR(class EEClassHashTable) PTR_EEClassHashTable;
63class EEClassHashTable : public NgenHashTable<EEClassHashTable, EEClassHashEntry, 4>
64{
65#ifdef DACCESS_COMPILE
66 friend class NativeImageDumper;
67#endif
68
69public:
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
119private:
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
130private:
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