comparison src/share/vm/classfile/altHashing.cpp @ 17709:f9e35a9dc8c7

8033792: AltHashing used jint for imprecise bit shifting Summary: AltHashing used jint the way of juint in bit shifting which could lead loss of precision. Fix by change _seed defined as juint. Reviewed-by: coleenp, ccheung Contributed-by: yumin.qi@oracle.com
author minqi
date Mon, 10 Feb 2014 21:29:14 -0800
parents f9be75d21404
children 4ca6dc0799b6
comparison
equal deleted inserted replaced
17707:7d28f4e15b61 17709:f9e35a9dc8c7
1 /* 1 /*
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
37 intptr_t hc = k->java_mirror()->mark()->hash(); 37 intptr_t hc = k->java_mirror()->mark()->hash();
38 return hc != markOopDesc::no_hash ? hc : os::random(); 38 return hc != markOopDesc::no_hash ? hc : os::random();
39 } 39 }
40 40
41 // Seed value used for each alternative hash calculated. 41 // Seed value used for each alternative hash calculated.
42 jint AltHashing::compute_seed() { 42 juint AltHashing::compute_seed() {
43 jlong nanos = os::javaTimeNanos(); 43 jlong nanos = os::javaTimeNanos();
44 jlong now = os::javaTimeMillis(); 44 jlong now = os::javaTimeMillis();
45 jint SEED_MATERIAL[8] = { 45 int SEED_MATERIAL[8] = {
46 (jint) object_hash(SystemDictionary::String_klass()), 46 (int) object_hash(SystemDictionary::String_klass()),
47 (jint) object_hash(SystemDictionary::System_klass()), 47 (int) object_hash(SystemDictionary::System_klass()),
48 (jint) os::random(), // current thread isn't a java thread 48 (int) os::random(), // current thread isn't a java thread
49 (jint) (((julong)nanos) >> 32), 49 (int) (((julong)nanos) >> 32),
50 (jint) nanos, 50 (int) nanos,
51 (jint) (((julong)now) >> 32), 51 (int) (((julong)now) >> 32),
52 (jint) now, 52 (int) now,
53 (jint) (os::javaTimeNanos() >> 2) 53 (int) (os::javaTimeNanos() >> 2)
54 }; 54 };
55 55
56 return murmur3_32(SEED_MATERIAL, 8); 56 return murmur3_32(SEED_MATERIAL, 8);
57 } 57 }
58 58
59 59
60 // Murmur3 hashing for Symbol 60 // Murmur3 hashing for Symbol
61 jint AltHashing::murmur3_32(jint seed, const jbyte* data, int len) { 61 juint AltHashing::murmur3_32(juint seed, const jbyte* data, int len) {
62 jint h1 = seed; 62 juint h1 = seed;
63 int count = len; 63 int count = len;
64 int offset = 0; 64 int offset = 0;
65 65
66 // body 66 // body
67 while (count >= 4) { 67 while (count >= 4) {
68 jint k1 = (data[offset] & 0x0FF) 68 juint k1 = (data[offset] & 0x0FF)
69 | (data[offset + 1] & 0x0FF) << 8 69 | (data[offset + 1] & 0x0FF) << 8
70 | (data[offset + 2] & 0x0FF) << 16 70 | (data[offset + 2] & 0x0FF) << 16
71 | data[offset + 3] << 24; 71 | data[offset + 3] << 24;
72 72
73 count -= 4; 73 count -= 4;
83 } 83 }
84 84
85 // tail 85 // tail
86 86
87 if (count > 0) { 87 if (count > 0) {
88 jint k1 = 0; 88 juint k1 = 0;
89 89
90 switch (count) { 90 switch (count) {
91 case 3: 91 case 3:
92 k1 ^= (data[offset + 2] & 0xff) << 16; 92 k1 ^= (data[offset + 2] & 0xff) << 16;
93 // fall through 93 // fall through
107 107
108 // finalization 108 // finalization
109 h1 ^= len; 109 h1 ^= len;
110 110
111 // finalization mix force all bits of a hash block to avalanche 111 // finalization mix force all bits of a hash block to avalanche
112 h1 ^= ((unsigned int)h1) >> 16; 112 h1 ^= h1 >> 16;
113 h1 *= 0x85ebca6b; 113 h1 *= 0x85ebca6b;
114 h1 ^= ((unsigned int)h1) >> 13; 114 h1 ^= h1 >> 13;
115 h1 *= 0xc2b2ae35; 115 h1 *= 0xc2b2ae35;
116 h1 ^= ((unsigned int)h1) >> 16; 116 h1 ^= h1 >> 16;
117 117
118 return h1; 118 return h1;
119 } 119 }
120 120
121 // Murmur3 hashing for Strings 121 // Murmur3 hashing for Strings
122 jint AltHashing::murmur3_32(jint seed, const jchar* data, int len) { 122 juint AltHashing::murmur3_32(juint seed, const jchar* data, int len) {
123 jint h1 = seed; 123 juint h1 = seed;
124 124
125 int off = 0; 125 int off = 0;
126 int count = len; 126 int count = len;
127 127
128 // body 128 // body
129 while (count >= 2) { 129 while (count >= 2) {
130 jchar d1 = data[off++] & 0xFFFF; 130 jchar d1 = data[off++] & 0xFFFF;
131 jchar d2 = data[off++]; 131 jchar d2 = data[off++];
132 jint k1 = (d1 | d2 << 16); 132 juint k1 = (d1 | d2 << 16);
133 133
134 count -= 2; 134 count -= 2;
135 135
136 k1 *= 0xcc9e2d51; 136 k1 *= 0xcc9e2d51;
137 k1 = Integer_rotateLeft(k1, 15); 137 k1 = Integer_rotateLeft(k1, 15);
143 } 143 }
144 144
145 // tail 145 // tail
146 146
147 if (count > 0) { 147 if (count > 0) {
148 int k1 = data[off]; 148 juint k1 = (juint)data[off];
149 149
150 k1 *= 0xcc9e2d51; 150 k1 *= 0xcc9e2d51;
151 k1 = Integer_rotateLeft(k1, 15); 151 k1 = Integer_rotateLeft(k1, 15);
152 k1 *= 0x1b873593; 152 k1 *= 0x1b873593;
153 h1 ^= k1; 153 h1 ^= k1;
155 155
156 // finalization 156 // finalization
157 h1 ^= len * 2; // (Character.SIZE / Byte.SIZE); 157 h1 ^= len * 2; // (Character.SIZE / Byte.SIZE);
158 158
159 // finalization mix force all bits of a hash block to avalanche 159 // finalization mix force all bits of a hash block to avalanche
160 h1 ^= ((unsigned int)h1) >> 16; 160 h1 ^= h1 >> 16;
161 h1 *= 0x85ebca6b; 161 h1 *= 0x85ebca6b;
162 h1 ^= ((unsigned int)h1) >> 13; 162 h1 ^= h1 >> 13;
163 h1 *= 0xc2b2ae35; 163 h1 *= 0xc2b2ae35;
164 h1 ^= ((unsigned int)h1) >> 16; 164 h1 ^= h1 >> 16;
165 165
166 return h1; 166 return h1;
167 } 167 }
168 168
169 // Hash used for the seed. 169 // Hash used for the seed.
170 jint AltHashing::murmur3_32(jint seed, const int* data, int len) { 170 juint AltHashing::murmur3_32(juint seed, const int* data, int len) {
171 jint h1 = seed; 171 juint h1 = seed;
172 172
173 int off = 0; 173 int off = 0;
174 int end = len; 174 int end = len;
175 175
176 // body 176 // body
177 while (off < end) { 177 while (off < end) {
178 jint k1 = data[off++]; 178 juint k1 = (juint)data[off++];
179 179
180 k1 *= 0xcc9e2d51; 180 k1 *= 0xcc9e2d51;
181 k1 = Integer_rotateLeft(k1, 15); 181 k1 = Integer_rotateLeft(k1, 15);
182 k1 *= 0x1b873593; 182 k1 *= 0x1b873593;
183 183
191 // finalization 191 // finalization
192 192
193 h1 ^= len * 4; // (Integer.SIZE / Byte.SIZE); 193 h1 ^= len * 4; // (Integer.SIZE / Byte.SIZE);
194 194
195 // finalization mix force all bits of a hash block to avalanche 195 // finalization mix force all bits of a hash block to avalanche
196 h1 ^= ((juint)h1) >> 16; 196 h1 ^= h1 >> 16;
197 h1 *= 0x85ebca6b; 197 h1 *= 0x85ebca6b;
198 h1 ^= ((juint)h1) >> 13; 198 h1 ^= h1 >> 13;
199 h1 *= 0xc2b2ae35; 199 h1 *= 0xc2b2ae35;
200 h1 ^= ((juint)h1) >> 16; 200 h1 ^= h1 >> 16;
201 201
202 return h1; 202 return h1;
203 } 203 }
204 204
205 jint AltHashing::murmur3_32(const int* data, int len) { 205 juint AltHashing::murmur3_32(const int* data, int len) {
206 return murmur3_32(0, data, len); 206 return murmur3_32(0, data, len);
207 } 207 }
208 208
209 #ifndef PRODUCT 209 #ifndef PRODUCT
210 // Overloaded versions for internal test. 210 // Overloaded versions for internal test.
211 jint AltHashing::murmur3_32(const jbyte* data, int len) { 211 juint AltHashing::murmur3_32(const jbyte* data, int len) {
212 return murmur3_32(0, data, len); 212 return murmur3_32(0, data, len);
213 } 213 }
214 214
215 jint AltHashing::murmur3_32(const jchar* data, int len) { 215 juint AltHashing::murmur3_32(const jchar* data, int len) {
216 return murmur3_32(0, data, len); 216 return murmur3_32(0, data, len);
217 } 217 }
218 218
219 // Internal test for alternate hashing. Translated from JDK version 219 // Internal test for alternate hashing. Translated from JDK version
220 // test/sun/misc/Hashing.java 220 // test/sun/misc/Hashing.java
249 vector[i] = (jbyte) i; 249 vector[i] = (jbyte) i;
250 } 250 }
251 251
252 // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255} 252 // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255}
253 for (int i = 0; i < 256; i++) { 253 for (int i = 0; i < 256; i++) {
254 jint hash = murmur3_32(256 - i, vector, i); 254 juint hash = murmur3_32(256 - i, vector, i);
255 hashes[i * 4] = (jbyte) hash; 255 hashes[i * 4] = (jbyte) hash;
256 hashes[i * 4 + 1] = (jbyte) (((juint)hash) >> 8); 256 hashes[i * 4 + 1] = (jbyte)(hash >> 8);
257 hashes[i * 4 + 2] = (jbyte) (((juint)hash) >> 16); 257 hashes[i * 4 + 2] = (jbyte)(hash >> 16);
258 hashes[i * 4 + 3] = (jbyte) (((juint)hash) >> 24); 258 hashes[i * 4 + 3] = (jbyte)(hash >> 24);
259 } 259 }
260 260
261 // hash to get const result. 261 // hash to get const result.
262 juint final_hash = murmur3_32(hashes, 4*256); 262 juint final_hash = murmur3_32(hashes, 4*256);
263 263
267 MURMUR3_32_X86_CHECK_VALUE, 267 MURMUR3_32_X86_CHECK_VALUE,
268 final_hash)); 268 final_hash));
269 } 269 }
270 270
271 void AltHashing::testEquivalentHashes() { 271 void AltHashing::testEquivalentHashes() {
272 jint jbytes, jchars, ints; 272 juint jbytes, jchars, ints;
273 273
274 // printf("testEquivalentHashes\n"); 274 // printf("testEquivalentHashes\n");
275 275
276 jbytes = murmur3_32(TWO_BYTE, 2); 276 jbytes = murmur3_32(TWO_BYTE, 2);
277 jchars = murmur3_32(ONE_CHAR, 1); 277 jchars = murmur3_32(ONE_CHAR, 1);