Skip to content

Commit 97ce13d

Browse files
authored
Type key hash tweaks. (#61234)
* use HashTypeKey(), remove ComputeHash() * nonrecursive HashTypeHandle * remove instrumentation from pendingload.cpp * two more uses of `ComputeHash()` * Make GCC happy * couple tweaks * unnecessary full fences.
1 parent 2266376 commit 97ce13d

File tree

8 files changed

+38
-77
lines changed

8 files changed

+38
-77
lines changed

src/coreclr/vm/clsload.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3634,7 +3634,7 @@ ClassLoader::LoadTypeHandleForTypeKey_Body(
36343634
}
36353635
EX_HOOK
36363636
{
3637-
LOG((LF_CLASSLOADER, LL_INFO10, "Caught an exception loading: %x, %0x (Module)\n", pTypeKey->IsConstructed() ? pTypeKey->ComputeHash() : pTypeKey->GetTypeToken(), pTypeKey->GetModule()));
3637+
LOG((LF_CLASSLOADER, LL_INFO10, "Caught an exception loading: %x, %0x (Module)\n", pTypeKey->IsConstructed() ? HashTypeKey(pTypeKey) : pTypeKey->GetTypeToken(), pTypeKey->GetModule()));
36383638

36393639
if (!GetThread()->HasThreadStateNC(Thread::TSNC_LoadsTypeViolation))
36403640
{

src/coreclr/vm/dacenumerablehash.inl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,9 @@ void DacEnumerableHashTable<DAC_ENUM_HASH_ARGS>::BaseInsertEntry(DacEnumerableHa
135135
// Prepare to link the new entry at the head of the bucket chain.
136136
pVolatileEntry->m_pNextEntry = (GetBuckets())[dwBucket];
137137

138-
// Make sure that all writes to the entry are visible before publishing the entry.
139-
MemoryBarrier();
140-
141138
// Publish the entry by pointing the bucket at it.
142-
(GetBuckets())[dwBucket] = pVolatileEntry;
139+
// Make sure that all writes to the entry are visible before publishing the entry.
140+
VolatileStore(&(GetBuckets())[dwBucket], pVolatileEntry);
143141

144142
m_cEntries++;
145143

@@ -207,15 +205,13 @@ void DacEnumerableHashTable<DAC_ENUM_HASH_ARGS>::GrowTable()
207205
}
208206

209207
// Make sure that all writes are visible before publishing the new array.
210-
MemoryBarrier();
211-
m_pBuckets = pNewBuckets;
208+
VolatileStore(&m_pBuckets, pNewBuckets);
212209

213210
// The new number of buckets has to be published last (prior to this readers may miscalculate a bucket
214211
// index, but the result will always be in range and they'll simply walk the wrong chain and get a miss,
215212
// prompting a retry under the lock). If we let the count become visible unordered wrt to the bucket array
216213
// itself a reader could potentially read buckets from beyond the end of the old bucket list).
217-
MemoryBarrier();
218-
m_cBuckets = cNewBuckets;
214+
VolatileStore(&m_cBuckets, cNewBuckets);
219215
}
220216

221217
// Returns the next prime larger (or equal to) than the number given.

src/coreclr/vm/gdbjit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ class NotifyGdb
387387
static count_t Hash(key_t k)
388388
{
389389
LIMITED_METHOD_CONTRACT;
390-
return k->ComputeHash();
390+
return HashTypeKey(k);
391391
}
392392

393393
static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(key_t(),VALUE()); }

src/coreclr/vm/pendingload.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ BOOL PendingTypeLoadTable::InsertValue(PendingTypeLoadEntry *pData)
114114

115115
_ASSERTE(m_dwNumBuckets != 0);
116116

117-
DWORD dwHash = pData->GetTypeKey().ComputeHash();
117+
DWORD dwHash = HashTypeKey(&pData->GetTypeKey());
118118
DWORD dwBucket = dwHash % m_dwNumBuckets;
119119
PendingTypeLoadTable::TableEntry * pNewEntry = AllocNewEntry();
120120
if (pNewEntry == NULL)
@@ -130,7 +130,6 @@ BOOL PendingTypeLoadTable::InsertValue(PendingTypeLoadEntry *pData)
130130
return TRUE;
131131
}
132132

133-
134133
BOOL PendingTypeLoadTable::DeleteValue(TypeKey *pKey)
135134
{
136135
CONTRACTL
@@ -145,7 +144,7 @@ BOOL PendingTypeLoadTable::DeleteValue(TypeKey *pKey)
145144

146145
_ASSERTE(m_dwNumBuckets != 0);
147146

148-
DWORD dwHash = pKey->ComputeHash();
147+
DWORD dwHash = HashTypeKey(pKey);
149148
DWORD dwBucket = dwHash % m_dwNumBuckets;
150149
PendingTypeLoadTable::TableEntry * pSearch;
151150
PendingTypeLoadTable::TableEntry **ppPrev = &m_pBuckets[dwBucket];
@@ -182,7 +181,7 @@ PendingTypeLoadTable::TableEntry *PendingTypeLoadTable::FindItem(TypeKey *pKey)
182181
_ASSERTE(m_dwNumBuckets != 0);
183182

184183

185-
DWORD dwHash = pKey->ComputeHash();
184+
DWORD dwHash = HashTypeKey(pKey);
186185
DWORD dwBucket = dwHash % m_dwNumBuckets;
187186
PendingTypeLoadTable::TableEntry * pSearch;
188187

src/coreclr/vm/pendingload.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class PendingTypeLoadEntry
166166
}
167167
#endif //DACCESS_COMPILE
168168

169-
TypeKey GetTypeKey()
169+
TypeKey& GetTypeKey()
170170
{
171171
LIMITED_METHOD_CONTRACT;
172172
return m_typeKey;

src/coreclr/vm/typehash.cpp

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ DWORD EETypeHashTable::GetCount()
141141
return BaseGetElementCount();
142142
}
143143

144-
static DWORD HashTypeHandle(DWORD level, TypeHandle t);
144+
static DWORD HashTypeHandle(TypeHandle t);
145145

146146
// Calculate hash value for a type def or instantiated type def
147-
static DWORD HashPossiblyInstantiatedType(DWORD level, mdTypeDef token, Instantiation inst)
147+
static DWORD HashPossiblyInstantiatedType(mdTypeDef token, Instantiation inst)
148148
{
149149
CONTRACTL
150150
{
@@ -161,25 +161,18 @@ static DWORD HashPossiblyInstantiatedType(DWORD level, mdTypeDef token, Instanti
161161
dwHash = ((dwHash << 5) + dwHash) ^ token;
162162
if (!inst.IsEmpty())
163163
{
164-
dwHash = ((dwHash << 5) + dwHash) ^ inst.GetNumArgs();
165-
166-
// Hash two levels of the hiearchy. A simple nesting of generics instantiations is
167-
// pretty common in generic collections, e.g.: ICollection<KeyValuePair<TKey, TValue>>
168-
if (level < 2)
164+
// Hash n type parameters
165+
for (DWORD i = 0; i < inst.GetNumArgs(); i++)
169166
{
170-
// Hash n type parameters
171-
for (DWORD i = 0; i < inst.GetNumArgs(); i++)
172-
{
173-
dwHash = ((dwHash << 5) + dwHash) ^ HashTypeHandle(level+1, inst[i]);
174-
}
167+
dwHash = ((dwHash << 5) + dwHash) ^ inst[i].AsTAddr();
175168
}
176169
}
177170

178171
return dwHash;
179172
}
180173

181174
// Calculate hash value for a function pointer type
182-
static DWORD HashFnPtrType(DWORD level, BYTE callConv, DWORD numArgs, TypeHandle *retAndArgTypes)
175+
static DWORD HashFnPtrType(BYTE callConv, DWORD numArgs, TypeHandle *retAndArgTypes)
183176
{
184177
WRAPPER_NO_CONTRACT;
185178
SUPPORTS_DAC;
@@ -188,31 +181,29 @@ static DWORD HashFnPtrType(DWORD level, BYTE callConv, DWORD numArgs, TypeHandle
188181
dwHash = ((dwHash << 5) + dwHash) ^ ELEMENT_TYPE_FNPTR;
189182
dwHash = ((dwHash << 5) + dwHash) ^ callConv;
190183
dwHash = ((dwHash << 5) + dwHash) ^ numArgs;
191-
if (level < 1)
184+
185+
for (DWORD i = 0; i <= numArgs; i++)
192186
{
193-
for (DWORD i = 0; i <= numArgs; i++)
194-
{
195-
dwHash = ((dwHash << 5) + dwHash) ^ HashTypeHandle(level+1, retAndArgTypes[i]);
196-
}
187+
dwHash = ((dwHash << 5) + dwHash) ^ retAndArgTypes[i].AsTAddr();
197188
}
198189

199190
return dwHash;
200191
}
201192

202193
// Calculate hash value for an array/pointer/byref type
203-
static DWORD HashParamType(DWORD level, CorElementType kind, TypeHandle typeParam)
194+
static DWORD HashParamType(CorElementType kind, TypeHandle typeParam)
204195
{
205196
WRAPPER_NO_CONTRACT;
206197
INT_PTR dwHash = 5381;
207198

208199
dwHash = ((dwHash << 5) + dwHash) ^ kind;
209-
dwHash = ((dwHash << 5) + dwHash) ^ HashTypeHandle(level, typeParam);
200+
dwHash = ((dwHash << 5) + dwHash) ^ typeParam.AsTAddr();
210201

211202
return dwHash;
212203
}
213204

214205
// Calculate hash value from type handle
215-
static DWORD HashTypeHandle(DWORD level, TypeHandle t)
206+
static DWORD HashTypeHandle(TypeHandle t)
216207
{
217208
CONTRACTL
218209
{
@@ -229,29 +220,30 @@ static DWORD HashTypeHandle(DWORD level, TypeHandle t)
229220

230221
if (t.HasTypeParam())
231222
{
232-
retVal = HashParamType(level, t.GetInternalCorElementType(), t.GetTypeParam());
233-
}
234-
else if (t.IsGenericVariable())
235-
{
236-
retVal = (dac_cast<PTR_TypeVarTypeDesc>(t.AsTypeDesc())->GetToken());
223+
retVal = HashParamType(t.GetInternalCorElementType(), t.GetTypeParam());
237224
}
238225
else if (t.HasInstantiation())
239226
{
240-
retVal = HashPossiblyInstantiatedType(level, t.GetCl(), t.GetInstantiation());
227+
retVal = HashPossiblyInstantiatedType(t.GetCl(), t.GetInstantiation());
241228
}
242229
else if (t.IsFnPtrType())
243230
{
244231
FnPtrTypeDesc* pTD = t.AsFnPtrType();
245-
retVal = HashFnPtrType(level, pTD->GetCallConv(), pTD->GetNumArgs(), pTD->GetRetAndArgTypesPointer());
232+
retVal = HashFnPtrType(pTD->GetCallConv(), pTD->GetNumArgs(), pTD->GetRetAndArgTypesPointer());
233+
}
234+
else if (t.IsGenericVariable())
235+
{
236+
_ASSERTE(!"Generic variables are unexpected here.");
237+
retVal = t.AsTAddr();
246238
}
247239
else
248-
retVal = HashPossiblyInstantiatedType(level, t.GetCl(), Instantiation());
240+
retVal = HashPossiblyInstantiatedType(t.GetCl(), Instantiation());
249241

250242
return retVal;
251243
}
252244

253245
// Calculate hash value from key
254-
static DWORD HashTypeKey(TypeKey* pKey)
246+
DWORD HashTypeKey(TypeKey* pKey)
255247
{
256248
CONTRACTL
257249
{
@@ -265,15 +257,15 @@ static DWORD HashTypeKey(TypeKey* pKey)
265257

266258
if (pKey->GetKind() == ELEMENT_TYPE_CLASS)
267259
{
268-
return HashPossiblyInstantiatedType(0, pKey->GetTypeToken(), pKey->GetInstantiation());
260+
return HashPossiblyInstantiatedType(pKey->GetTypeToken(), pKey->GetInstantiation());
269261
}
270262
else if (pKey->GetKind() == ELEMENT_TYPE_FNPTR)
271263
{
272-
return HashFnPtrType(0, pKey->GetCallConv(), pKey->GetNumArgs(), pKey->GetRetAndArgTypes());
264+
return HashFnPtrType(pKey->GetCallConv(), pKey->GetNumArgs(), pKey->GetRetAndArgTypes());
273265
}
274266
else
275267
{
276-
return HashParamType(0, pKey->GetKind(), pKey->GetElementType());
268+
return HashParamType(pKey->GetKind(), pKey->GetElementType());
277269
}
278270
}
279271

@@ -552,7 +544,7 @@ VOID EETypeHashTable::InsertValue(TypeHandle data)
552544

553545
pNewEntry->SetTypeHandle(data);
554546

555-
BaseInsertEntry(HashTypeHandle(0, data), pNewEntry);
547+
BaseInsertEntry(HashTypeHandle(data), pNewEntry);
556548
}
557549

558550
#endif // #ifndef DACCESS_COMPILE

src/coreclr/vm/typehash.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
//
2727
//========================================================================================
2828

29+
DWORD HashTypeKey(TypeKey* pKey);
30+
2931
// One of these is present for each element in the table
3032
// It simply chains together (hash,data) pairs
3133
typedef DPTR(struct EETypeHashEntry) PTR_EETypeHashEntry;

src/coreclr/vm/typekey.h

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ class TypeKey
213213
return TypeKey::Equals(this, pKey);
214214
}
215215

216-
// Comparison and hashing
217216
static BOOL Equals(const TypeKey *pKey1, const TypeKey *pKey2)
218217
{
219218
WRAPPER_NO_CONTRACT;
@@ -257,33 +256,6 @@ class TypeKey
257256
return TRUE;
258257
}
259258
}
260-
261-
DWORD ComputeHash() const
262-
{
263-
LIMITED_METHOD_CONTRACT;
264-
DWORD_PTR hashLarge;
265-
266-
if (m_kind == ELEMENT_TYPE_CLASS)
267-
{
268-
hashLarge = ((DWORD_PTR)u.asClass.m_pModule ^ (DWORD_PTR)u.asClass.m_numGenericArgs ^ (DWORD_PTR)u.asClass.m_typeDef);
269-
}
270-
else if (CorTypeInfo::IsModifier_NoThrow(m_kind) || m_kind == ELEMENT_TYPE_VALUETYPE)
271-
{
272-
hashLarge = (u.asParamType.m_paramType ^ (DWORD_PTR) u.asParamType.m_rank);
273-
}
274-
else hashLarge = 0;
275-
276-
#if POINTER_BITS == 32
277-
return hashLarge;
278-
#else
279-
DWORD hash = *(DWORD *)&hashLarge;
280-
for (unsigned i = 1; i < POINTER_BITS / 32; i++)
281-
{
282-
hash ^= ((DWORD *)&hashLarge)[i];
283-
}
284-
return hash;
285-
#endif
286-
}
287259
};
288260

289261

0 commit comments

Comments
 (0)