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#include "common.h"
6#include "versionresilienthashcode.h"
7#include "typehashingalgorithms.h"
8
9bool GetVersionResilientTypeHashCode(IMDInternalImport *pMDImport, mdExportedType token, int * pdwHashCode)
10{
11 CONTRACTL
12 {
13 NOTHROW;
14 GC_NOTRIGGER;
15 SO_TOLERANT;
16 MODE_ANY;
17 PRECONDITION(CheckPointer(pdwHashCode));
18 }
19 CONTRACTL_END
20
21 _ASSERTE(TypeFromToken(token) == mdtTypeDef ||
22 TypeFromToken(token) == mdtTypeRef ||
23 TypeFromToken(token) == mdtExportedType);
24 _ASSERTE(!IsNilToken(token));
25
26 HRESULT hr;
27 LPCUTF8 szNamespace;
28 LPCUTF8 szName;
29 bool hasTypeToken = true;
30 int hashcode = 0;
31
32 while (hasTypeToken)
33 {
34 if (IsNilToken(token))
35 return false;
36
37 switch (TypeFromToken(token))
38 {
39 case mdtTypeDef:
40 if (FAILED(pMDImport->GetNameOfTypeDef(token, &szName, &szNamespace)))
41 return false;
42 hr = pMDImport->GetNestedClassProps(token, &token);
43 if (hr == CLDB_E_RECORD_NOTFOUND)
44 hasTypeToken = false;
45 else if (FAILED(hr))
46 return false;
47 break;
48
49 case mdtTypeRef:
50 if (FAILED(pMDImport->GetNameOfTypeRef(token, &szNamespace, &szName)))
51 return false;
52 if (FAILED(pMDImport->GetResolutionScopeOfTypeRef(token, &token)))
53 return false;
54 hasTypeToken = (TypeFromToken(token) == mdtTypeRef);
55 break;
56
57 case mdtExportedType:
58 if (FAILED(pMDImport->GetExportedTypeProps(token, &szNamespace, &szName, &token, NULL, NULL)))
59 return false;
60 hasTypeToken = (TypeFromToken(token) == mdtExportedType);
61 break;
62
63 default:
64 return false;
65 }
66
67 hashcode ^= ComputeNameHashCode(szNamespace, szName);
68 }
69
70 *pdwHashCode = hashcode;
71
72 return true;
73}
74
75#ifndef DACCESS_COMPILE
76int GetVersionResilientTypeHashCode(TypeHandle type)
77{
78 STANDARD_VM_CONTRACT;
79
80 if (!type.IsTypeDesc())
81 {
82 MethodTable *pMT = type.AsMethodTable();
83
84 _ASSERTE(!pMT->IsArray());
85 _ASSERTE(!IsNilToken(pMT->GetCl()));
86
87 LPCUTF8 szNamespace;
88 LPCUTF8 szName;
89 IfFailThrow(pMT->GetMDImport()->GetNameOfTypeDef(pMT->GetCl(), &szName, &szNamespace));
90 int hashcode = ComputeNameHashCode(szNamespace, szName);
91
92 MethodTable *pMTEnclosing = pMT->LoadEnclosingMethodTable(CLASS_LOAD_UNRESTOREDTYPEKEY);
93 if (pMTEnclosing != NULL)
94 {
95 hashcode = ComputeNestedTypeHashCode(GetVersionResilientTypeHashCode(TypeHandle(pMTEnclosing)), hashcode);
96 }
97
98 if (!pMT->IsGenericTypeDefinition() && pMT->HasInstantiation())
99 {
100 return ComputeGenericInstanceHashCode(hashcode,
101 pMT->GetInstantiation().GetNumArgs(), pMT->GetInstantiation(), GetVersionResilientTypeHashCode);
102 }
103 else
104 {
105 return hashcode;
106 }
107 }
108 else
109 if (type.IsArray())
110 {
111 ArrayTypeDesc *pArray = type.AsArray();
112 return ComputeArrayTypeHashCode(GetVersionResilientTypeHashCode(pArray->GetArrayElementTypeHandle()), pArray->GetRank());
113 }
114 else
115 if (type.IsPointer())
116 {
117 return ComputePointerTypeHashCode(GetVersionResilientTypeHashCode(type.AsTypeDesc()->GetTypeParam()));
118 }
119 else
120 if (type.IsByRef())
121 {
122 return ComputeByrefTypeHashCode(GetVersionResilientTypeHashCode(type.AsTypeDesc()->GetTypeParam()));
123 }
124
125 assert(false);
126 return 0;
127}
128
129int GetVersionResilientMethodHashCode(MethodDesc *pMD)
130{
131 STANDARD_VM_CONTRACT;
132
133 int hashCode = GetVersionResilientTypeHashCode(TypeHandle(pMD->GetMethodTable()));
134
135 // Todo: Add signature to hash.
136 if (pMD->GetNumGenericMethodArgs() > 0)
137 {
138 hashCode ^= ComputeGenericInstanceHashCode(ComputeNameHashCode(pMD->GetName()), pMD->GetNumGenericMethodArgs(), pMD->GetMethodInstantiation(), GetVersionResilientTypeHashCode);
139 }
140 else
141 {
142 hashCode ^= ComputeNameHashCode(pMD->GetName());
143 }
144
145 return hashCode;
146}
147#endif // DACCESS_COMPILE
148