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: instmethhash.h
6//
7
8
9//
10
11//
12// ============================================================================
13
14#ifndef _INSTMETHHASH_H
15#define _INSTMETHHASH_H
16
17#include "ngenhash.h"
18
19class AllocMemTracker;
20
21//========================================================================================
22// The hash table types defined in this header file are used by the loader to
23// look up instantiation-specific methods:
24// - per-instantiation static method stubs e.g ArrayList<string>.HelperMeth
25// - instantiated methods e.g. Array.Sort<string>
26//
27// Each persisted Module has an InstMethodHashTable used for such methods that
28// were ngen'ed into that module. See ceeload.hpp for more information about ngen modules.
29//
30// Methods created at runtime are placed in an InstMethHashTable in BaseDomain.
31//
32// Keys are always derivable from the data stored in the table (MethodDesc)
33//
34// Keys are always derivable from the data stored in the table (MethodDesc),
35// with the exception of some flag values that cannot be computed for unrestore MDs
36// (we need to be able to look up entries without restoring other entries along
37// the way!)
38//
39// The table is safe for multiple readers and a single writer i.e. only one thread
40// can be in InsertMethodDesc but multiple threads can be in FindMethodDesc.
41//========================================================================================
42
43class InstMethodHashTable;
44
45// One of these is present for each element in the table
46// It simply chains together (hash,data) pairs
47typedef DPTR(struct InstMethodHashEntry) PTR_InstMethodHashEntry;
48typedef struct InstMethodHashEntry
49{
50 PTR_MethodDesc GetMethod();
51 DWORD GetFlags();
52#ifndef DACCESS_COMPILE
53 void SetMethodAndFlags(MethodDesc *pMethod, DWORD dwFlags);
54#endif // !DACCESS_COMPILE
55
56 enum
57 {
58 UnboxingStub = 0x01,
59 RequiresInstArg = 0x02
60 };
61
62private:
63 friend class InstMethodHashTable;
64#ifdef DACCESS_COMPILE
65 friend class NativeImageDumper;
66#endif
67
68 PTR_MethodDesc data;
69} InstMethodHashEntry_t;
70
71
72// The method-desc hash table itself
73typedef DPTR(class InstMethodHashTable) PTR_InstMethodHashTable;
74class InstMethodHashTable : public NgenHashTable<InstMethodHashTable, InstMethodHashEntry, 4>
75{
76#ifdef DACCESS_COMPILE
77 friend class NativeImageDumper;
78#endif
79
80public:
81 // This is the allocator
82 PTR_LoaderAllocator m_pLoaderAllocator;
83
84#ifdef _DEBUG
85private:
86 Volatile<LONG> m_dwSealCount; // Can more types be added to the table?
87
88public:
89 void InitUnseal() { LIMITED_METHOD_CONTRACT; m_dwSealCount = 0; }
90 bool IsUnsealed() { LIMITED_METHOD_CONTRACT; return (m_dwSealCount == 0); }
91 void Seal() { LIMITED_METHOD_CONTRACT; FastInterlockIncrement(&m_dwSealCount); }
92 void Unseal() { LIMITED_METHOD_CONTRACT; FastInterlockDecrement(&m_dwSealCount); }
93#endif // _DEBUG
94
95private:
96 InstMethodHashTable();
97 ~InstMethodHashTable();
98
99public:
100 static InstMethodHashTable* Create(LoaderAllocator *pAllocator, Module *pModule, DWORD dwNumBuckets, AllocMemTracker *pamTracker);
101
102private:
103 friend class NgenHashTable<InstMethodHashTable, InstMethodHashEntry, 4>;
104
105#ifndef DACCESS_COMPILE
106 InstMethodHashTable(Module *pModule, LoaderHeap *pHeap, DWORD cInitialBuckets) :
107 NgenHashTable<InstMethodHashTable, InstMethodHashEntry, 4>(pModule, pHeap, cInitialBuckets) {}
108#endif
109 void operator delete(void *p);
110
111public:
112 // Add a method desc to the hash table
113 void InsertMethodDesc(MethodDesc *pMD);
114
115 // Look up a method in the hash table
116 MethodDesc *FindMethodDesc(TypeHandle declaringType,
117 mdMethodDef token,
118 BOOL unboxingStub,
119 Instantiation inst,
120 BOOL getSharedNotStub);
121
122 BOOL ContainsMethodDesc(MethodDesc* pMD);
123
124#if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE)
125 // Save the hash table and any method descriptors referenced by it
126 void Save(DataImage *image, CorProfileData *pProfileData);
127
128 // Record fixups required on the hash table
129 // Recurse into method descriptors referenced by it
130 void Fixup(DataImage *image);
131
132 bool ShouldSave(DataImage *pImage, InstMethodHashEntry_t *pEntry);
133 bool IsHotEntry(InstMethodHashEntry_t *pEntry, CorProfileData *pProfileData);
134 bool SaveEntry(DataImage *pImage, CorProfileData *pProfileData, InstMethodHashEntry_t *pOldEntry, InstMethodHashEntry_t *pNewEntry, EntryMappingTable *pMap);
135 void FixupEntry(DataImage *pImage, InstMethodHashEntry_t *pEntry, void *pFixupBase, DWORD cbFixupOffset);
136#endif // FEATURE_PREJIT && !DACCESS_COMPILE
137
138 // An iterator for the table, currently used only by Module::Save
139 struct Iterator
140 {
141 public:
142 // This iterator can be reused for walking different tables
143 void Reset();
144 Iterator();
145
146 Iterator(InstMethodHashTable * pTable);
147 ~Iterator();
148
149 private:
150 friend class InstMethodHashTable;
151
152 void Init();
153
154 InstMethodHashTable*m_pTable;
155 BaseIterator m_sIterator;
156 bool m_fIterating;
157 };
158
159 BOOL FindNext(Iterator *it, InstMethodHashEntry **ppEntry);
160
161 DWORD GetCount();
162
163#ifdef DACCESS_COMPILE
164 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
165 void EnumMemoryRegionsForEntry(InstMethodHashEntry_t *pEntry, CLRDataEnumMemoryFlags flags);
166#endif
167
168private:
169 LoaderAllocator* GetLoaderAllocator();
170};
171
172#endif /* _INSTMETHHASH_H */
173