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//
15inline 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
42inline 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
52inline 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
66inline static int ComputePointerTypeHashCode(int pointeeTypeHashcode)
67{
68 LIMITED_METHOD_CONTRACT;
69
70 return (pointeeTypeHashcode + _rotl(pointeeTypeHashcode, 5)) ^ 0x12D0;
71}
72
73inline static int ComputeByrefTypeHashCode(int parameterTypeHashcode)
74{
75 LIMITED_METHOD_CONTRACT;
76
77 return (parameterTypeHashcode + _rotl(parameterTypeHashcode, 7)) ^ 0x4C85;
78}
79
80inline static int ComputeNestedTypeHashCode(int enclosingTypeHashcode, int nestedTypeNameHash)
81{
82 LIMITED_METHOD_CONTRACT;
83
84 return (enclosingTypeHashcode + _rotl(enclosingTypeHashcode, 11)) ^ nestedTypeNameHash;
85}
86
87template <typename TA, typename TB>
88inline 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