Path: blob/master/src/hotspot/share/classfile/altHashing.cpp
40949 views
/*1* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324/*25* halfsiphash code adapted from reference implementation26* (https://github.com/veorq/SipHash/blob/master/halfsiphash.c)27* which is distributed with the following copyright:28*29* SipHash reference C implementation30*31* Copyright (c) 2016 Jean-Philippe Aumasson <[email protected]>32*33* To the extent possible under law, the author(s) have dedicated all copyright34* and related and neighboring rights to this software to the public domain35* worldwide. This software is distributed without any warranty.36*37* You should have received a copy of the CC0 Public Domain Dedication along38* with this software. If not, see39* <http://creativecommons.org/publicdomain/zero/1.0/>.40*/4142#include "precompiled.hpp"43#include "classfile/altHashing.hpp"44#include "classfile/vmClasses.hpp"45#include "oops/klass.inline.hpp"46#include "oops/markWord.hpp"47#include "oops/oop.inline.hpp"48#include "runtime/os.hpp"4950// Get the hash code of the classes mirror if it exists, otherwise just51// return a random number, which is one of the possible hash code used for52// objects. We don't want to call the synchronizer hash code to install53// this value because it may safepoint.54static intptr_t object_hash(Klass* k) {55intptr_t hc = k->java_mirror()->mark().hash();56return hc != markWord::no_hash ? hc : os::random();57}5859// Seed value used for each alternative hash calculated.60uint64_t AltHashing::compute_seed() {61uint64_t nanos = os::javaTimeNanos();62uint64_t now = os::javaTimeMillis();63uint32_t SEED_MATERIAL[8] = {64(uint32_t) object_hash(vmClasses::String_klass()),65(uint32_t) object_hash(vmClasses::System_klass()),66(uint32_t) os::random(), // current thread isn't a java thread67(uint32_t) (((uint64_t)nanos) >> 32),68(uint32_t) nanos,69(uint32_t) (((uint64_t)now) >> 32),70(uint32_t) now,71(uint32_t) (os::javaTimeNanos() >> 2)72};7374return halfsiphash_64(SEED_MATERIAL, 8);75}7677// utility function copied from java/lang/Integer78static uint32_t Integer_rotateLeft(uint32_t i, int distance) {79return (i << distance) | (i >> (32 - distance));80}8182static void halfsiphash_rounds(uint32_t v[4], int rounds) {83while (rounds-- > 0) {84v[0] += v[1];85v[1] = Integer_rotateLeft(v[1], 5);86v[1] ^= v[0];87v[0] = Integer_rotateLeft(v[0], 16);88v[2] += v[3];89v[3] = Integer_rotateLeft(v[3], 8);90v[3] ^= v[2];91v[0] += v[3];92v[3] = Integer_rotateLeft(v[3], 7);93v[3] ^= v[0];94v[2] += v[1];95v[1] = Integer_rotateLeft(v[1], 13);96v[1] ^= v[2];97v[2] = Integer_rotateLeft(v[2], 16);98}99}100101static void halfsiphash_adddata(uint32_t v[4], uint32_t newdata, int rounds) {102v[3] ^= newdata;103halfsiphash_rounds(v, rounds);104v[0] ^= newdata;105}106107static void halfsiphash_init32(uint32_t v[4], uint64_t seed) {108v[0] = seed & 0xffffffff;109v[1] = seed >> 32;110v[2] = 0x6c796765 ^ v[0];111v[3] = 0x74656462 ^ v[1];112}113114static void halfsiphash_init64(uint32_t v[4], uint64_t seed) {115halfsiphash_init32(v, seed);116v[1] ^= 0xee;117}118119uint32_t halfsiphash_finish32(uint32_t v[4], int rounds) {120v[2] ^= 0xff;121halfsiphash_rounds(v, rounds);122return (v[1] ^ v[3]);123}124125static uint64_t halfsiphash_finish64(uint32_t v[4], int rounds) {126uint64_t rv;127v[2] ^= 0xee;128halfsiphash_rounds(v, rounds);129rv = v[1] ^ v[3];130v[1] ^= 0xdd;131halfsiphash_rounds(v, rounds);132rv |= (uint64_t)(v[1] ^ v[3]) << 32;133return rv;134}135136// HalfSipHash-2-4 (32-bit output) for Symbols137uint32_t AltHashing::halfsiphash_32(uint64_t seed, const uint8_t* data, int len) {138uint32_t v[4];139uint32_t newdata;140int off = 0;141int count = len;142143halfsiphash_init32(v, seed);144145// body146while (count >= 4) {147148// Avoid sign extension with 0x0ff149newdata = (data[off] & 0x0FF)150| (data[off + 1] & 0x0FF) << 8151| (data[off + 2] & 0x0FF) << 16152| data[off + 3] << 24;153154count -= 4;155off += 4;156157halfsiphash_adddata(v, newdata, 2);158}159160// tail161newdata = ((uint32_t)len) << 24; // (Byte.SIZE / Byte.SIZE);162163if (count > 0) {164switch (count) {165case 3:166newdata |= (data[off + 2] & 0x0ff) << 16;167// fall through168case 2:169newdata |= (data[off + 1] & 0x0ff) << 8;170// fall through171case 1:172newdata |= (data[off] & 0x0ff);173// fall through174}175}176177halfsiphash_adddata(v, newdata, 2);178179// finalization180return halfsiphash_finish32(v, 4);181}182183// HalfSipHash-2-4 (32-bit output) for Strings184uint32_t AltHashing::halfsiphash_32(uint64_t seed, const uint16_t* data, int len) {185uint32_t v[4];186uint32_t newdata;187int off = 0;188int count = len;189190halfsiphash_init32(v, seed);191192// body193while (count >= 2) {194uint16_t d1 = data[off++] & 0x0FFFF;195uint16_t d2 = data[off++];196newdata = (d1 | d2 << 16);197198count -= 2;199200halfsiphash_adddata(v, newdata, 2);201}202203// tail204newdata = ((uint32_t)len * 2) << 24; // (Character.SIZE / Byte.SIZE);205if (count > 0) {206newdata |= (uint32_t)data[off];207}208halfsiphash_adddata(v, newdata, 2);209210// finalization211return halfsiphash_finish32(v, 4);212}213214// HalfSipHash-2-4 (64-bit output) for integers (used to create seed)215uint64_t AltHashing::halfsiphash_64(uint64_t seed, const uint32_t* data, int len) {216uint32_t v[4];217218int off = 0;219int end = len;220221halfsiphash_init64(v, seed);222223// body224while (off < end) {225halfsiphash_adddata(v, (uint32_t)data[off++], 2);226}227228// tail (always empty, as body is always 32-bit chunks)229230// finalization231halfsiphash_adddata(v, ((uint32_t)len * 4) << 24, 2); // (Integer.SIZE / Byte.SIZE);232return halfsiphash_finish64(v, 4);233}234235// HalfSipHash-2-4 (64-bit output) for integers (used to create seed)236uint64_t AltHashing::halfsiphash_64(const uint32_t* data, int len) {237return halfsiphash_64((uint64_t)0, data, len);238}239240241