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#include "common.h"
11#include "typeequivalencehash.hpp"
12#include "ngenhash.inl"
13
14#ifdef FEATURE_TYPEEQUIVALENCE
15TypeEquivalenceHashTable::EquivalenceMatch TypeEquivalenceHashTable::CheckEquivalence(TypeHandle thA, TypeHandle thB)
16{
17 CONTRACTL
18 {
19 THROWS;
20 GC_TRIGGERS;
21 MODE_ANY;
22 }
23 CONTRACTL_END;
24
25 LookupContext lookupContext;
26 NgenHashValue hash = TypeEquivalenceEntry::HashTypeHandles(thA, thB);
27
28 PTR_TypeEquivalenceEntry search = BaseFindFirstEntryByHash(hash, &lookupContext);
29 while (search != NULL)
30 {
31 if (search->Match(thA, thB))
32 {
33 return search->GetEquivalence() ? Match : NoMatch;
34 }
35
36 search = BaseFindNextEntryByHash(&lookupContext);
37 }
38 return MatchUnknown;
39}
40
41#ifndef DACCESS_COMPILE
42/*static*/
43TypeEquivalenceHashTable *TypeEquivalenceHashTable::Create(AppDomain *pAppDomain, DWORD dwNumBuckets, CrstExplicitInit *pCrst)
44{
45 CONTRACTL
46 {
47 THROWS;
48 GC_TRIGGERS;
49 MODE_ANY;
50 INJECT_FAULT(COMPlusThrowOM(););
51 }
52 CONTRACTL_END;
53
54 AllocMemTracker amt;
55 LoaderHeap *pHeap = pAppDomain->GetLowFrequencyHeap();
56 TypeEquivalenceHashTable *pThis = (TypeEquivalenceHashTable*)amt.Track(pHeap->AllocMem((S_SIZE_T)sizeof(TypeEquivalenceHashTable)));
57
58 // The base class gets initialized through chaining of constructors.
59 // Use in-place new to create instance.
60 new (pThis) TypeEquivalenceHashTable(pHeap, dwNumBuckets, pCrst);
61 amt.SuppressRelease();
62
63 return pThis;
64}
65
66void TypeEquivalenceHashTable::RecordEquivalence(TypeHandle thA, TypeHandle thB, TypeEquivalenceHashTable::EquivalenceMatch match)
67{
68 CONTRACTL
69 {
70 THROWS;
71 GC_TRIGGERS;
72 MODE_ANY;
73 INJECT_FAULT(COMPlusThrowOM(););
74 PRECONDITION(match != TypeEquivalenceHashTable::MatchUnknown);
75 }
76 CONTRACTL_END;
77
78 CrstHolder ch(m_pHashTableCrst);
79
80 // Was there a race in calculating equivalence and this thread lost?
81 // If so, return
82 EquivalenceMatch checkedMatch = CheckEquivalence(thA, thB);
83 if (checkedMatch != TypeEquivalenceHashTable::MatchUnknown)
84 {
85 _ASSERTE(checkedMatch == match);
86 return;
87 }
88
89 AllocMemTracker amt;
90 PTR_TypeEquivalenceEntry pNewEntry = BaseAllocateEntry(&amt);
91 amt.SuppressRelease();
92
93 pNewEntry->SetData(thA, thB, match == TypeEquivalenceHashTable::Match ? true : false);
94 NgenHashValue hash = TypeEquivalenceEntry::HashTypeHandles(thA, thB);
95
96 BaseInsertEntry(hash, pNewEntry);
97}
98#endif // !DACCESS_COMPILE
99#endif // FEATURE_TYPEEQUIVALENCE
100
101