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 | // Generic functions to compute the hashcode value of types |
7 | // --------------------------------------------------------------------------- |
8 | |
9 | #pragma once |
10 | #include <stdlib.h> |
11 | |
12 | // |
13 | // Returns the hashcode value of the 'src' string |
14 | // |
15 | inline static int ComputeNameHashCode(LPCUTF8 src) |
16 | { |
17 | LIMITED_METHOD_CONTRACT; |
18 | |
19 | if (src == NULL || *src == '\0') |
20 | return 0; |
21 | |
22 | int hash1 = 0x6DA3B944; |
23 | int hash2 = 0; |
24 | |
25 | // DIFFERENT FROM CORERT: We hash UTF-8 bytes here, while CoreRT hashes UTF-16 characters. |
26 | |
27 | for (COUNT_T i = 0; src[i] != '\0'; i += 2) |
28 | { |
29 | hash1 = (hash1 + _rotl(hash1, 5)) ^ src[i]; |
30 | if (src[i + 1] != '\0') |
31 | hash2 = (hash2 + _rotl(hash2, 5)) ^ src[i + 1]; |
32 | else |
33 | break; |
34 | } |
35 | |
36 | hash1 += _rotl(hash1, 8); |
37 | hash2 += _rotl(hash2, 8); |
38 | |
39 | return hash1 ^ hash2; |
40 | } |
41 | |
42 | inline static int ComputeNameHashCode(LPCUTF8 pszNamespace, LPCUTF8 pszName) |
43 | { |
44 | LIMITED_METHOD_CONTRACT; |
45 | |
46 | // DIFFERENT FROM CORERT: CoreRT hashes the full name as one string ("namespace.name"), |
47 | // as the full name is already available. In CoreCLR we normally only have separate |
48 | // strings for namespace and name, thus we hash them separately. |
49 | return ComputeNameHashCode(pszNamespace) ^ ComputeNameHashCode(pszName); |
50 | } |
51 | |
52 | inline static int ComputeArrayTypeHashCode(int elementTypeHashcode, int rank) |
53 | { |
54 | LIMITED_METHOD_CONTRACT; |
55 | |
56 | // DIFFERENT FROM CORERT: This is much simplified compared to CoreRT, to avoid converting.rank to string. |
57 | // For single-dimensinal array, the result is identical to CoreRT. |
58 | int hashCode = 0xd5313556 + rank; |
59 | if (rank == 1) |
60 | _ASSERTE(hashCode == ComputeNameHashCode("System.Array`1" )); |
61 | |
62 | hashCode = (hashCode + _rotl(hashCode, 13)) ^ elementTypeHashcode; |
63 | return (hashCode + _rotl(hashCode, 15)); |
64 | } |
65 | |
66 | inline static int ComputePointerTypeHashCode(int pointeeTypeHashcode) |
67 | { |
68 | LIMITED_METHOD_CONTRACT; |
69 | |
70 | return (pointeeTypeHashcode + _rotl(pointeeTypeHashcode, 5)) ^ 0x12D0; |
71 | } |
72 | |
73 | inline static int ComputeByrefTypeHashCode(int parameterTypeHashcode) |
74 | { |
75 | LIMITED_METHOD_CONTRACT; |
76 | |
77 | return (parameterTypeHashcode + _rotl(parameterTypeHashcode, 7)) ^ 0x4C85; |
78 | } |
79 | |
80 | inline static int ComputeNestedTypeHashCode(int enclosingTypeHashcode, int nestedTypeNameHash) |
81 | { |
82 | LIMITED_METHOD_CONTRACT; |
83 | |
84 | return (enclosingTypeHashcode + _rotl(enclosingTypeHashcode, 11)) ^ nestedTypeNameHash; |
85 | } |
86 | |
87 | template <typename TA, typename TB> |
88 | inline static int ComputeGenericInstanceHashCode(int definitionHashcode, int arity, const TA& genericTypeArguments, int (*getHashCode)(TB)) |
89 | { |
90 | LIMITED_METHOD_CONTRACT; |
91 | |
92 | int hashcode = definitionHashcode; |
93 | for (int i = 0; i < arity; i++) |
94 | { |
95 | int argumentHashCode = getHashCode(genericTypeArguments[i]); |
96 | hashcode = (hashcode + _rotl(hashcode, 13)) ^ argumentHashCode; |
97 | } |
98 | return (hashcode + _rotl(hashcode, 15)); |
99 | } |
100 | |