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 |
15 | TypeEquivalenceHashTable::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*/ |
43 | TypeEquivalenceHashTable *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 | |
66 | void 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 | |