Mercurial > hg > truffle
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); |