Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/classfile/altHashing.cpp
32285 views
1
/*
2
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
/*
26
* halfsiphash code adapted from reference implementation
27
* (https://github.com/veorq/SipHash/blob/master/halfsiphash.c)
28
* which is distributed with the following copyright:
29
*
30
* SipHash reference C implementation
31
*
32
* Copyright (c) 2016 Jean-Philippe Aumasson <[email protected]>
33
*
34
* To the extent possible under law, the author(s) have dedicated all copyright
35
* and related and neighboring rights to this software to the public domain
36
* worldwide. This software is distributed without any warranty.
37
*
38
* You should have received a copy of the CC0 Public Domain Dedication along
39
* with this software. If not, see
40
* <http://creativecommons.org/publicdomain/zero/1.0/>.
41
*/
42
43
#include "precompiled.hpp"
44
#include "classfile/altHashing.hpp"
45
#include "classfile/systemDictionary.hpp"
46
#include "oops/markOop.hpp"
47
#include "runtime/os.hpp"
48
49
// Get the hash code of the classes mirror if it exists, otherwise just
50
// return a random number, which is one of the possible hash code used for
51
// objects. We don't want to call the synchronizer hash code to install
52
// this value because it may safepoint.
53
intptr_t object_hash(Klass* k) {
54
intptr_t hc = k->java_mirror()->mark()->hash();
55
return hc != markOopDesc::no_hash ? hc : os::random();
56
}
57
58
// Seed value used for each alternative hash calculated.
59
uint64_t AltHashing::compute_seed() {
60
uint64_t nanos = os::javaTimeNanos();
61
uint64_t now = os::javaTimeMillis();
62
uint32_t SEED_MATERIAL[8] = {
63
(uint32_t) object_hash(SystemDictionary::String_klass()),
64
(uint32_t) object_hash(SystemDictionary::System_klass()),
65
(uint32_t) os::random(), // current thread isn't a java thread
66
(uint32_t) (((uint64_t)nanos) >> 32),
67
(uint32_t) nanos,
68
(uint32_t) (((uint64_t)now) >> 32),
69
(uint32_t) now,
70
(uint32_t) (os::javaTimeNanos() >> 2)
71
};
72
73
return halfsiphash_64(SEED_MATERIAL, 8);
74
}
75
76
// utility function copied from java/lang/Integer
77
static uint32_t Integer_rotateLeft(uint32_t i, int distance) {
78
return (i << distance) | (i >> (32 - distance));
79
}
80
81
static void halfsiphash_rounds(uint32_t v[4], int rounds) {
82
while (rounds-- > 0) {
83
v[0] += v[1];
84
v[1] = Integer_rotateLeft(v[1], 5);
85
v[1] ^= v[0];
86
v[0] = Integer_rotateLeft(v[0], 16);
87
v[2] += v[3];
88
v[3] = Integer_rotateLeft(v[3], 8);
89
v[3] ^= v[2];
90
v[0] += v[3];
91
v[3] = Integer_rotateLeft(v[3], 7);
92
v[3] ^= v[0];
93
v[2] += v[1];
94
v[1] = Integer_rotateLeft(v[1], 13);
95
v[1] ^= v[2];
96
v[2] = Integer_rotateLeft(v[2], 16);
97
}
98
}
99
100
static void halfsiphash_adddata(uint32_t v[4], uint32_t newdata, int rounds) {
101
v[3] ^= newdata;
102
halfsiphash_rounds(v, rounds);
103
v[0] ^= newdata;
104
}
105
106
static void halfsiphash_init32(uint32_t v[4], uint64_t seed) {
107
v[0] = seed & 0xffffffff;
108
v[1] = seed >> 32;
109
v[2] = 0x6c796765 ^ v[0];
110
v[3] = 0x74656462 ^ v[1];
111
}
112
113
static void halfsiphash_init64(uint32_t v[4], uint64_t seed) {
114
halfsiphash_init32(v, seed);
115
v[1] ^= 0xee;
116
}
117
118
uint32_t halfsiphash_finish32(uint32_t v[4], int rounds) {
119
v[2] ^= 0xff;
120
halfsiphash_rounds(v, rounds);
121
return (v[1] ^ v[3]);
122
}
123
124
static uint64_t halfsiphash_finish64(uint32_t v[4], int rounds) {
125
uint64_t rv;
126
v[2] ^= 0xee;
127
halfsiphash_rounds(v, rounds);
128
rv = v[1] ^ v[3];
129
v[1] ^= 0xdd;
130
halfsiphash_rounds(v, rounds);
131
rv |= (uint64_t)(v[1] ^ v[3]) << 32;
132
return rv;
133
}
134
135
// HalfSipHash-2-4 (32-bit output) for Symbols
136
uint32_t AltHashing::halfsiphash_32(uint64_t seed, const uint8_t* data, int len) {
137
uint32_t v[4];
138
uint32_t newdata;
139
int off = 0;
140
int count = len;
141
142
halfsiphash_init32(v, seed);
143
// body
144
while (count >= 4) {
145
// Avoid sign extension with 0x0ff
146
newdata = (data[off] & 0x0FF)
147
| (data[off + 1] & 0x0FF) << 8
148
| (data[off + 2] & 0x0FF) << 16
149
| data[off + 3] << 24;
150
151
count -= 4;
152
off += 4;
153
154
halfsiphash_adddata(v, newdata, 2);
155
}
156
157
// tail
158
newdata = ((uint32_t)len) << 24; // (Byte.SIZE / Byte.SIZE);
159
160
if (count > 0) {
161
switch (count) {
162
case 3:
163
newdata |= (data[off + 2] & 0x0ff) << 16;
164
// fall through
165
case 2:
166
newdata |= (data[off + 1] & 0x0ff) << 8;
167
// fall through
168
case 1:
169
newdata |= (data[off] & 0x0ff);
170
// fall through
171
}
172
}
173
174
halfsiphash_adddata(v, newdata, 2);
175
176
// finalization
177
return halfsiphash_finish32(v, 4);
178
}
179
180
// HalfSipHash-2-4 (32-bit output) for Strings
181
uint32_t AltHashing::halfsiphash_32(uint64_t seed, const uint16_t* data, int len) {
182
uint32_t v[4];
183
uint32_t newdata;
184
int off = 0;
185
int count = len;
186
187
halfsiphash_init32(v, seed);
188
189
// body
190
while (count >= 2) {
191
uint16_t d1 = data[off++] & 0x0FFFF;
192
uint16_t d2 = data[off++];
193
newdata = (d1 | d2 << 16);
194
195
count -= 2;
196
197
halfsiphash_adddata(v, newdata, 2);
198
}
199
200
// tail
201
newdata = ((uint32_t)len * 2) << 24; // (Character.SIZE / Byte.SIZE);
202
if (count > 0) {
203
newdata |= (uint32_t)data[off];
204
}
205
halfsiphash_adddata(v, newdata, 2);
206
207
// finalization
208
return halfsiphash_finish32(v, 4);
209
}
210
211
// HalfSipHash-2-4 (64-bit output) for integers (used to create seed)
212
uint64_t AltHashing::halfsiphash_64(uint64_t seed, const uint32_t* data, int len) {
213
uint32_t v[4];
214
215
int off = 0;
216
int end = len;
217
218
halfsiphash_init64(v, seed);
219
220
// body
221
while (off < end) {
222
halfsiphash_adddata(v, (uint32_t)data[off++], 2);
223
}
224
225
// tail (always empty, as body is always 32-bit chunks)
226
227
// finalization
228
halfsiphash_adddata(v, ((uint32_t)len * 4) << 24, 2); // (Integer.SIZE / Byte.SIZE);
229
return halfsiphash_finish64(v, 4);
230
}
231
232
// HalfSipHash-2-4 (64-bit output) for integers (used to create seed)
233
uint64_t AltHashing::halfsiphash_64(const uint32_t* data, int len) {
234
return halfsiphash_64((uint64_t)0, data, len);
235
}
236
237
#ifndef PRODUCT
238
void AltHashing::testHalfsiphash_32_ByteArray() {
239
const int factor = 4;
240
241
uint8_t vector[256];
242
uint8_t hashes[factor * 256];
243
244
for (int i = 0; i < 256; i++) {
245
vector[i] = (uint8_t) i;
246
}
247
248
// Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255}
249
for (int i = 0; i < 256; i++) {
250
uint32_t hash = AltHashing::halfsiphash_32(256 - i, vector, i);
251
hashes[i * factor] = (uint8_t) hash;
252
hashes[i * factor + 1] = (uint8_t)(hash >> 8);
253
hashes[i * factor + 2] = (uint8_t)(hash >> 16);
254
hashes[i * factor + 3] = (uint8_t)(hash >> 24);
255
}
256
257
// hash to get const result.
258
uint32_t final_hash = AltHashing::halfsiphash_32(0, hashes, factor*256);
259
260
// Value found using reference implementation for the hashes array.
261
//uint64_t k = 0; // seed
262
//uint32_t reference;
263
//halfsiphash((const uint8_t*)hashes, factor*256, (const uint8_t *)&k, (uint8_t*)&reference, 4);
264
//printf("0x%x", reference);
265
266
static const uint32_t HALFSIPHASH_32_BYTE_CHECK_VALUE = 0xd2be7fd8;
267
268
assert (HALFSIPHASH_32_BYTE_CHECK_VALUE == final_hash,
269
err_msg(
270
"Calculated hash result not as expected. Expected " UINT32_FORMAT " got " UINT32_FORMAT,
271
HALFSIPHASH_32_BYTE_CHECK_VALUE,
272
final_hash));
273
}
274
275
void AltHashing::testHalfsiphash_32_CharArray() {
276
const int factor = 2;
277
278
uint16_t vector[256];
279
uint16_t hashes[factor * 256];
280
281
for (int i = 0; i < 256; i++) {
282
vector[i] = (uint16_t) i;
283
}
284
285
// Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255}
286
for (int i = 0; i < 256; i++) {
287
uint32_t hash = AltHashing::halfsiphash_32(256 - i, vector, i);
288
hashes[i * factor] = (uint16_t) hash;
289
hashes[i * factor + 1] = (uint16_t)(hash >> 16);
290
}
291
292
// hash to get const result.
293
uint32_t final_hash = AltHashing::halfsiphash_32(0, hashes, factor*256);
294
295
// Value found using reference implementation for the hashes array.
296
//uint64_t k = 0; // seed
297
//uint32_t reference;
298
//halfsiphash((const uint8_t*)hashes, 2*factor*256, (const uint8_t *)&k, (uint8_t*)&reference, 4);
299
//printf("0x%x", reference);
300
301
static const uint32_t HALFSIPHASH_32_CHAR_CHECK_VALUE = 0x428bf8a5;
302
303
assert(HALFSIPHASH_32_CHAR_CHECK_VALUE == final_hash,
304
err_msg(
305
"Calculated hash result not as expected. Expected " UINT32_FORMAT " got " UINT32_FORMAT,
306
HALFSIPHASH_32_CHAR_CHECK_VALUE,
307
final_hash));
308
}
309
310
// Test against sample hashes published with the reference implementation:
311
// https://github.com/veorq/SipHash
312
void AltHashing::testHalfsiphash_64_FromReference() {
313
314
const uint64_t seed = 0x0706050403020100;
315
const uint64_t results[16] = {
316
0xc83cb8b9591f8d21, 0xa12ee55b178ae7d5,
317
0x8c85e4bc20e8feed, 0x99c7f5ae9f1fc77b,
318
0xb5f37b5fd2aa3673, 0xdba7ee6f0a2bf51b,
319
0xf1a63fae45107470, 0xb516001efb5f922d,
320
0x6c6211d8469d7028, 0xdc7642ec407ad686,
321
0x4caec8671cc8385b, 0x5ab1dc27adf3301e,
322
0x3e3ea94bc0a8eaa9, 0xe150f598795a4402,
323
0x1d5ff142f992a4a1, 0x60e426bf902876d6
324
};
325
uint32_t vector[16];
326
327
for (int i = 0; i < 16; i++)
328
vector[i] = 0x03020100 + i * 0x04040404;
329
330
for (int i = 0; i < 16; i++) {
331
uint64_t hash = AltHashing::halfsiphash_64(seed, vector, i);
332
assert(results[i] == hash,
333
err_msg(
334
"Calculated hash result not as expected. Round %d: "
335
"Expected " UINT64_FORMAT_X " got " UINT64_FORMAT_X "\n",
336
i,
337
results[i],
338
hash));
339
}
340
}
341
342
void AltHashing::test_alt_hash() {
343
testHalfsiphash_32_ByteArray();
344
testHalfsiphash_32_CharArray();
345
testHalfsiphash_64_FromReference();
346
}
347
#endif // PRODUCT
348
349