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// File: typehash.h
6//
7
8//
9
10#ifndef _TYPE_HASH_H
11#define _TYPE_HASH_H
12
13#include "ngenhash.h"
14
15//========================================================================================
16// This hash table is used by class loaders to look up constructed types:
17// arrays, pointers and instantiations of user-defined generic types.
18//
19// Each persisted module structure has an EETypeHashTable used for constructed types that
20// were ngen'ed into that module. See ceeload.hpp for more information about ngen modules.
21//
22// Types created at runtime are placed in an EETypeHashTable in BaseDomain.
23//
24// Keys are derivable from the data stored in the table (TypeHandle)
25// - for an instantiated type, the typedef module, typedef token, and instantiation
26// - for an array/pointer type, the CorElementType, rank, and type parameter
27//
28//========================================================================================
29
30// One of these is present for each element in the table
31// It simply chains together (hash,data) pairs
32typedef DPTR(struct EETypeHashEntry) PTR_EETypeHashEntry;
33typedef struct EETypeHashEntry
34{
35 TypeHandle GetTypeHandle();
36 void SetTypeHandle(TypeHandle handle);
37
38#ifdef FEATURE_PREJIT
39 // To make ngen saving much more efficient we support marking individual entries as hot (as determined by
40 // profile data).
41 bool IsHot();
42 void MarkAsHot();
43#endif // FEATURE_PREJIT
44
45#ifndef DACCESS_COMPILE
46 EETypeHashEntry& operator=(const EETypeHashEntry& src)
47 {
48 m_data.SetValueMaybeNull(src.m_data.GetValueMaybeNull());
49
50 return *this;
51 }
52#endif // !DACCESS_COMPILE
53
54 PTR_VOID GetData()
55 {
56 return ReadPointerMaybeNull(this, &EETypeHashEntry::m_data);
57 }
58
59private:
60 friend class EETypeHashTable;
61#ifdef DACCESS_COMPILE
62 friend class NativeImageDumper;
63#endif
64
65 RelativePointer<PTR_VOID> m_data;
66} EETypeHashEntry_t;
67
68
69// The type hash table itself
70typedef DPTR(class EETypeHashTable) PTR_EETypeHashTable;
71class EETypeHashTable : public NgenHashTable<EETypeHashTable, EETypeHashEntry, 2>
72{
73#ifdef DACCESS_COMPILE
74 friend class NativeImageDumper;
75#endif
76
77public:
78 // This is the domain in which the hash table is allocated
79 PTR_LoaderAllocator m_pAllocator;
80
81#ifdef _DEBUG
82private:
83 Volatile<LONG> m_dwSealCount; // Can more types be added to the table?
84
85public:
86 void InitUnseal() { LIMITED_METHOD_CONTRACT; m_dwSealCount = 0; }
87 bool IsUnsealed() { LIMITED_METHOD_CONTRACT; return (m_dwSealCount == 0); }
88 void Seal() { LIMITED_METHOD_CONTRACT; FastInterlockIncrement(&m_dwSealCount); }
89 void Unseal() { LIMITED_METHOD_CONTRACT; FastInterlockDecrement(&m_dwSealCount); }
90#endif // _DEBUG
91
92private:
93#ifndef DACCESS_COMPILE
94 EETypeHashTable();
95 ~EETypeHashTable();
96#endif
97public:
98 static EETypeHashTable *Create(LoaderAllocator *pAllocator, Module *pModule, DWORD dwNumBuckets, AllocMemTracker *pamTracker);
99
100private:
101 friend class NgenHashTable<EETypeHashTable, EETypeHashEntry, 2>;
102
103#ifndef DACCESS_COMPILE
104 EETypeHashTable(Module *pModule, LoaderHeap *pHeap, DWORD cInitialBuckets) :
105 NgenHashTable<EETypeHashTable, EETypeHashEntry, 2>(pModule, pHeap, cInitialBuckets) {}
106#endif
107 void operator delete(void *p);
108
109public:
110 // Insert a value in the hash table, key implicit in data
111 // Value must not be present in the table already
112 VOID InsertValue(TypeHandle data);
113
114 // Look up a value in the hash table, key explicit in pKey
115 // Return a null type handle if not found
116 TypeHandle GetValue(TypeKey* pKey);
117
118 BOOL ContainsValue(TypeHandle th);
119
120 // An iterator for the table
121 class Iterator
122 {
123 public:
124 // This iterator can be reused for walking different tables
125 void Reset();
126 Iterator();
127
128 Iterator(EETypeHashTable * pTable);
129 ~Iterator();
130
131 private:
132 friend class EETypeHashTable;
133
134 void Init();
135
136 EETypeHashTable *m_pTable;
137 BaseIterator m_sIterator;
138 bool m_fIterating;
139 };
140
141 BOOL FindNext(Iterator *it, EETypeHashEntry **ppEntry);
142
143 DWORD GetCount();
144
145#if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE)
146 // Save the hash table and any type descriptors referenced by it
147 // Template method tables (for arrays) must be saved separately
148 void Save(DataImage *image, Module *module, CorProfileData *profileData);
149
150 // Record fixups required on the hash table
151 // Recurse into type descriptors and template method tables referenced by it
152 void Fixup(DataImage *image);
153
154 bool ShouldSave(DataImage *pImage, EETypeHashEntry_t *pEntry);
155 bool IsHotEntry(EETypeHashEntry_t *pEntry, CorProfileData *pProfileData);
156 bool SaveEntry(DataImage *pImage, CorProfileData *pProfileData, EETypeHashEntry_t *pOldEntry, EETypeHashEntry_t *pNewEntry, EntryMappingTable *pMap);
157 void FixupEntry(DataImage *pImage, EETypeHashEntry_t *pEntry, void *pFixupBase, DWORD cbFixupOffset);
158#endif // FEATURE_PREJIT && !DACCESS_COMPILE
159
160#ifdef DACCESS_COMPILE
161 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
162 void EnumMemoryRegionsForEntry(EETypeHashEntry_t *pEntry, CLRDataEnumMemoryFlags flags);
163#endif
164
165private:
166 EETypeHashEntry_t * FindItem(TypeKey* pKey);
167 BOOL CompareInstantiatedType(TypeHandle t, Module *pModule, mdTypeDef token, Instantiation inst);
168 BOOL CompareFnPtrType(TypeHandle t, BYTE callConv, DWORD numArgs, TypeHandle *retAndArgTypes);
169 BOOL GrowHashTable();
170 LoaderAllocator* GetLoaderAllocator();
171};
172
173#endif /* _TYPE_HASH_H */
174
175