1 /* 2 * Copyright (c) 2012, 2024, 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 31 /* 32 SipHash reference C implementation 33 34 Copyright (c) 2016 Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com> 35 36 To the extent possible under law, the author(s) have dedicated all copyright 37 and related and neighboring rights to this software to the public domain 38 worldwide. This software is distributed without any warranty. 39 40 You should have received a copy of the CC0 Public Domain Dedication along 41 with 42 this software. If not, see 43 <http://creativecommons.org/publicdomain/zero/1.0/>. 44 */ 45 46 #include "precompiled.hpp" 47 #include "classfile/altHashing.hpp" 48 #include "classfile/vmClasses.hpp" 49 #include "oops/klass.inline.hpp" 50 #include "oops/markWord.hpp" 51 #include "oops/oop.inline.hpp" 52 #include "runtime/os.hpp" 53 54 // Get the hash code of the classes mirror if it exists, otherwise just 55 // return a random number, which is one of the possible hash code used for 56 // objects. We don't want to call the synchronizer hash code to install 57 // this value because it may safepoint. 58 static intptr_t object_hash(Klass* k) { 59 intptr_t hc = k->java_mirror()->mark().hash(); 60 return hc != markWord::no_hash ? hc : os::random(); 61 } 62 63 // Seed value used for each alternative hash calculated. 64 uint64_t AltHashing::compute_seed() { 65 uint64_t nanos = os::javaTimeNanos(); 66 uint64_t now = os::javaTimeMillis(); 67 uint32_t SEED_MATERIAL[8] = { 68 (uint32_t) object_hash(vmClasses::String_klass()), 69 (uint32_t) object_hash(vmClasses::System_klass()), 70 (uint32_t) os::random(), // current thread isn't a java thread 71 (uint32_t) (((uint64_t)nanos) >> 32), 72 (uint32_t) nanos, 73 (uint32_t) (((uint64_t)now) >> 32), 74 (uint32_t) now, 75 (uint32_t) (os::javaTimeNanos() >> 2) 76 }; 77 78 return halfsiphash_64(SEED_MATERIAL, 8); 79 } 80 81 // utility function copied from java/lang/Integer 82 static uint32_t Integer_rotateLeft(uint32_t i, int distance) { 83 return (i << distance) | (i >> (32 - distance)); 84 } 85 86 static void halfsiphash_rounds(uint32_t v[4], int rounds) { 87 while (rounds-- > 0) { 88 v[0] += v[1]; 89 v[1] = Integer_rotateLeft(v[1], 5); 90 v[1] ^= v[0]; 91 v[0] = Integer_rotateLeft(v[0], 16); 92 v[2] += v[3]; 93 v[3] = Integer_rotateLeft(v[3], 8); 94 v[3] ^= v[2]; 95 v[0] += v[3]; 96 v[3] = Integer_rotateLeft(v[3], 7); 97 v[3] ^= v[0]; 98 v[2] += v[1]; 99 v[1] = Integer_rotateLeft(v[1], 13); 100 v[1] ^= v[2]; 101 v[2] = Integer_rotateLeft(v[2], 16); 102 } 103 } 104 105 static void halfsiphash_adddata(uint32_t v[4], uint32_t newdata, int rounds) { 106 v[3] ^= newdata; 107 halfsiphash_rounds(v, rounds); 108 v[0] ^= newdata; 109 } 110 111 static void halfsiphash_init32(uint32_t v[4], uint64_t seed) { 112 v[0] = seed & 0xffffffff; 113 v[1] = (uint32_t)(seed >> 32); 114 v[2] = 0x6c796765 ^ v[0]; 115 v[3] = 0x74656462 ^ v[1]; 116 } 117 118 static void halfsiphash_init64(uint32_t v[4], uint64_t seed) { 119 halfsiphash_init32(v, seed); 120 v[1] ^= 0xee; 121 } 122 123 static uint32_t halfsiphash_finish32(uint32_t v[4], int rounds) { 124 v[2] ^= 0xff; 125 halfsiphash_rounds(v, rounds); 126 return (v[1] ^ v[3]); 127 } 128 129 static uint64_t halfsiphash_finish64(uint32_t v[4], int rounds) { 130 uint64_t rv; 131 v[2] ^= 0xee; 132 halfsiphash_rounds(v, rounds); 133 rv = v[1] ^ v[3]; 134 v[1] ^= 0xdd; 135 halfsiphash_rounds(v, rounds); 136 rv |= (uint64_t)(v[1] ^ v[3]) << 32; 137 return rv; 138 } 139 140 // HalfSipHash-2-4 (32-bit output) for Symbols 141 uint32_t AltHashing::halfsiphash_32(uint64_t seed, const void* in, int len) { 142 143 const unsigned char* data = (const unsigned char*)in; 144 uint32_t v[4]; 145 uint32_t newdata; 146 int off = 0; 147 int count = len; 148 149 halfsiphash_init32(v, seed); 150 151 // body 152 while (count >= 4) { 153 154 // Avoid sign extension with 0x0ff 155 newdata = (data[off] & 0x0FF) 156 | (data[off + 1] & 0x0FF) << 8 157 | (data[off + 2] & 0x0FF) << 16 158 | data[off + 3] << 24; 159 160 count -= 4; 161 off += 4; 162 163 halfsiphash_adddata(v, newdata, 2); 164 } 165 166 // tail 167 newdata = ((uint32_t)len) << 24; // (Byte.SIZE / Byte.SIZE); 168 169 if (count > 0) { 170 switch (count) { 171 case 3: 172 newdata |= (data[off + 2] & 0x0ff) << 16; 173 // fall through 174 case 2: 175 newdata |= (data[off + 1] & 0x0ff) << 8; 176 // fall through 177 case 1: 178 newdata |= (data[off] & 0x0ff); 179 // fall through 180 } 181 } 182 183 halfsiphash_adddata(v, newdata, 2); 184 185 // finalization 186 return halfsiphash_finish32(v, 4); 187 } 188 189 // HalfSipHash-2-4 (32-bit output) for Strings 190 uint32_t AltHashing::halfsiphash_32(uint64_t seed, const uint16_t* data, int len) { 191 uint32_t v[4]; 192 uint32_t newdata; 193 int off = 0; 194 int count = len; 195 196 halfsiphash_init32(v, seed); 197 198 // body 199 while (count >= 2) { 200 uint16_t d1 = data[off++] & 0x0FFFF; 201 uint16_t d2 = data[off++]; 202 newdata = (d1 | d2 << 16); 203 204 count -= 2; 205 206 halfsiphash_adddata(v, newdata, 2); 207 } 208 209 // tail 210 newdata = ((uint32_t)len * 2) << 24; // (Character.SIZE / Byte.SIZE); 211 if (count > 0) { 212 newdata |= (uint32_t)data[off]; 213 } 214 halfsiphash_adddata(v, newdata, 2); 215 216 // finalization 217 return halfsiphash_finish32(v, 4); 218 } 219 220 // HalfSipHash-2-4 (64-bit output) for integers (used to create seed) 221 uint64_t AltHashing::halfsiphash_64(uint64_t seed, const uint32_t* data, int len) { 222 uint32_t v[4]; 223 224 int off = 0; 225 int end = len; 226 227 halfsiphash_init64(v, seed); 228 229 // body 230 while (off < end) { 231 halfsiphash_adddata(v, (uint32_t)data[off++], 2); 232 } 233 234 // tail (always empty, as body is always 32-bit chunks) 235 236 // finalization 237 halfsiphash_adddata(v, ((uint32_t)len * 4) << 24, 2); // (Integer.SIZE / Byte.SIZE); 238 return halfsiphash_finish64(v, 4); 239 } 240 241 // HalfSipHash-2-4 (64-bit output) for integers (used to create seed) 242 uint64_t AltHashing::halfsiphash_64(const uint32_t* data, int len) { 243 return halfsiphash_64((uint64_t)0, data, len); 244 }