Mercurial > hg > icedtea8-forest > hotspot
changeset 10795:8adf45218add
8244955: Additional Fix for JDK-8240124
Reviewed-by: mbalao, andrew
author | vkempik |
---|---|
date | Wed, 23 Sep 2020 16:26:20 +0300 |
parents | fd3484fadbe3 |
children | 824065fb8b18 |
files | src/share/vm/classfile/altHashing.cpp src/share/vm/classfile/altHashing.hpp src/share/vm/classfile/symbolTable.cpp src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp src/share/vm/memory/filemap.cpp src/share/vm/oops/oop.cpp src/share/vm/oops/symbol.cpp |
diffstat | 8 files changed, 91 insertions(+), 114 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/classfile/altHashing.cpp Wed Sep 23 15:18:53 2020 +0300 +++ b/src/share/vm/classfile/altHashing.cpp Wed Sep 23 16:26:20 2020 +0300 @@ -115,6 +115,12 @@ v[1] ^= 0xee; } +uint32_t halfsiphash_finish32(uint32_t v[4], int rounds) { + v[2] ^= 0xff; + halfsiphash_rounds(v, rounds); + return (v[1] ^ v[3]); +} + static uint64_t halfsiphash_finish64(uint32_t v[4], int rounds) { uint64_t rv; v[2] ^= 0xee; @@ -126,14 +132,14 @@ return rv; } -// HalfSipHash-2-4 (64-bit output) for Symbols -uint64_t AltHashing::halfsiphash_64(uint64_t seed, const int8_t* data, int len) { +// HalfSipHash-2-4 (32-bit output) for Symbols +uint32_t AltHashing::halfsiphash_32(uint64_t seed, const uint8_t* data, int len) { uint32_t v[4]; uint32_t newdata; int off = 0; int count = len; - halfsiphash_init64(v, seed); + halfsiphash_init32(v, seed); // body while (count >= 4) { // Avoid sign extension with 0x0ff @@ -168,17 +174,17 @@ halfsiphash_adddata(v, newdata, 2); // finalization - return halfsiphash_finish64(v, 4); + return halfsiphash_finish32(v, 4); } -// HalfSipHash-2-4 (64-bit output) for Strings -uint64_t AltHashing::halfsiphash_64(uint64_t seed, const uint16_t* data, int len) { +// HalfSipHash-2-4 (32-bit output) for Strings +uint32_t AltHashing::halfsiphash_32(uint64_t seed, const uint16_t* data, int len) { uint32_t v[4]; uint32_t newdata; int off = 0; int count = len; - halfsiphash_init64(v, seed); + halfsiphash_init32(v, seed); // body while (count >= 2) { @@ -199,7 +205,7 @@ halfsiphash_adddata(v, newdata, 2); // finalization - return halfsiphash_finish64(v, 4); + return halfsiphash_finish32(v, 4); } // HalfSipHash-2-4 (64-bit output) for integers (used to create seed) @@ -229,44 +235,44 @@ } #ifndef PRODUCT - void AltHashing::testHalfsiphash_64_ByteArray() { - // printf("testHalfsiphash_64_CharArray\n"); + void AltHashing::testHalfsiphash_32_ByteArray() { const int factor = 4; - int8_t vector[256]; - int8_t hashes[factor * 256]; + uint8_t vector[256]; + uint8_t hashes[factor * 256]; for (int i = 0; i < 256; i++) { - vector[i] = (int8_t) i; + vector[i] = (uint8_t) i; } // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255} for (int i = 0; i < 256; i++) { - uint64_t hash = AltHashing::halfsiphash_64(256 - i, vector, i); - hashes[i * factor] = (int8_t) hash; - hashes[i * factor + 1] = (int8_t)(hash >> 8); - hashes[i * factor + 2] = (int8_t)(hash >> 16); - hashes[i * factor + 3] = (int8_t)(hash >> 24); + uint32_t hash = AltHashing::halfsiphash_32(256 - i, vector, i); + hashes[i * factor] = (uint8_t) hash; + hashes[i * factor + 1] = (uint8_t)(hash >> 8); + hashes[i * factor + 2] = (uint8_t)(hash >> 16); + hashes[i * factor + 3] = (uint8_t)(hash >> 24); } // hash to get const result. - uint64_t final_hash = AltHashing::halfsiphash_64(0, hashes, factor*256); + uint32_t final_hash = AltHashing::halfsiphash_32(0, hashes, factor*256); // Value found using reference implementation for the hashes array. - // halfsiphash((const uint8_t*)hashes, factor*256, (const uint8_t *)&k, - // (uint8_t*)&reference, 8); - - static const uint64_t HALFSIPHASH_64_BYTE_CHECK_VALUE = 0x15a7911e30917ee8; + //uint64_t k = 0; // seed + //uint32_t reference; + //halfsiphash((const uint8_t*)hashes, factor*256, (const uint8_t *)&k, (uint8_t*)&reference, 4); + //printf("0x%x", reference); - assert (HALFSIPHASH_64_BYTE_CHECK_VALUE == final_hash, + static const uint32_t HALFSIPHASH_32_BYTE_CHECK_VALUE = 0xd2be7fd8; + + assert (HALFSIPHASH_32_BYTE_CHECK_VALUE == final_hash, err_msg( - "Calculated hash result not as expected. Expected " UINT64_FORMAT " got " UINT64_FORMAT, - HALFSIPHASH_64_BYTE_CHECK_VALUE, + "Calculated hash result not as expected. Expected " UINT32_FORMAT " got " UINT32_FORMAT, + HALFSIPHASH_32_BYTE_CHECK_VALUE, final_hash)); } - void AltHashing::testHalfsiphash_64_CharArray() { - // printf("testHalfsiphash_64_CharArray\n"); + void AltHashing::testHalfsiphash_32_CharArray() { const int factor = 2; uint16_t vector[256]; @@ -278,30 +284,32 @@ // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255} for (int i = 0; i < 256; i++) { - uint64_t hash = AltHashing::halfsiphash_64(256 - i, vector, i); + uint32_t hash = AltHashing::halfsiphash_32(256 - i, vector, i); hashes[i * factor] = (uint16_t) hash; hashes[i * factor + 1] = (uint16_t)(hash >> 16); } // hash to get const result. - uint64_t final_hash = AltHashing::halfsiphash_64(0, hashes, factor*256); + uint32_t final_hash = AltHashing::halfsiphash_32(0, hashes, factor*256); // Value found using reference implementation for the hashes array. - // halfsiphash((const uint8_t*)hashes, 2*factor*256, (const uint8_t *)&k, - // (uint8_t*)&reference, 8); - static const uint64_t HALFSIPHASH_64_CHAR_CHECK_VALUE = 0xf392d8a6a9e24103; + //uint64_t k = 0; // seed + //uint32_t reference; + //halfsiphash((const uint8_t*)hashes, 2*factor*256, (const uint8_t *)&k, (uint8_t*)&reference, 4); + //printf("0x%x", reference); - assert(HALFSIPHASH_64_CHAR_CHECK_VALUE == final_hash, + static const uint32_t HALFSIPHASH_32_CHAR_CHECK_VALUE = 0x428bf8a5; + + assert(HALFSIPHASH_32_CHAR_CHECK_VALUE == final_hash, err_msg( - "Calculated hash result not as expected. Expected " UINT64_FORMAT " got " UINT64_FORMAT, - HALFSIPHASH_64_CHAR_CHECK_VALUE, + "Calculated hash result not as expected. Expected " UINT32_FORMAT " got " UINT32_FORMAT, + HALFSIPHASH_32_CHAR_CHECK_VALUE, final_hash)); } // Test against sample hashes published with the reference implementation: // https://github.com/veorq/SipHash void AltHashing::testHalfsiphash_64_FromReference() { - // printf("testHalfsiphash_64_FromReference\n"); const uint64_t seed = 0x0706050403020100; const uint64_t results[16] = { @@ -332,8 +340,8 @@ } void AltHashing::test_alt_hash() { - testHalfsiphash_64_ByteArray(); - testHalfsiphash_64_CharArray(); + testHalfsiphash_32_ByteArray(); + testHalfsiphash_32_CharArray(); testHalfsiphash_64_FromReference(); } #endif // PRODUCT
--- a/src/share/vm/classfile/altHashing.hpp Wed Sep 23 15:18:53 2020 +0300 +++ b/src/share/vm/classfile/altHashing.hpp Wed Sep 23 16:26:20 2020 +0300 @@ -39,17 +39,17 @@ static uint64_t halfsiphash_64(uint64_t seed, const uint32_t* data, int len); #ifndef PRODUCT // Hashing functions used for internal testing - static void testHalfsiphash_64_ByteArray(); - static void testHalfsiphash_64_CharArray(); + static void testHalfsiphash_32_ByteArray(); + static void testHalfsiphash_32_CharArray(); static void testHalfsiphash_64_FromReference(); #endif // PRODUCT public: static uint64_t compute_seed(); // For Symbols - static uint64_t halfsiphash_64(uint64_t seed, const int8_t* data, int len); + static uint32_t halfsiphash_32(uint64_t seed, const uint8_t* data, int len); // For Strings - static uint64_t halfsiphash_64(uint64_t seed, const uint16_t* data, int len); + static uint32_t halfsiphash_32(uint64_t seed, const uint16_t* data, int len); NOT_PRODUCT(static void test_alt_hash();) }; #endif // SHARE_VM_CLASSFILE_ALTHASHING_HPP
--- a/src/share/vm/classfile/symbolTable.cpp Wed Sep 23 15:18:53 2020 +0300 +++ b/src/share/vm/classfile/symbolTable.cpp Wed Sep 23 16:26:20 2020 +0300 @@ -224,7 +224,7 @@ // Pick hashing algorithm. unsigned int SymbolTable::hash_symbol(const char* s, int len) { return use_alternate_hashcode() ? - AltHashing::halfsiphash_64(seed(), (const int8_t*)s, len) : + AltHashing::halfsiphash_32(seed(), (const uint8_t*)s, len) : java_lang_String::hash_code(s, len); } @@ -650,7 +650,7 @@ // Pick hashing algorithm unsigned int StringTable::hash_string(const jchar* s, int len) { - return use_alternate_hashcode() ? AltHashing::halfsiphash_64(seed(), s, len) : + return use_alternate_hashcode() ? AltHashing::halfsiphash_32(seed(), s, len) : java_lang_String::hash_code(s, len); }
--- a/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp Wed Sep 23 15:18:53 2020 +0300 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp Wed Sep 23 16:26:20 2020 +0300 @@ -150,7 +150,7 @@ assert(worker_id < _nlists, "Invalid worker id"); entry->set_obj(NULL); - entry->set_java_hash(0); + entry->set_hash(0); if (_cached[worker_id].length() < _max_list_length) { // Cache is not full @@ -237,14 +237,10 @@ _table = new G1StringDedupTable(_min_size); } -void G1StringDedupTable::add(typeArrayOop value, uint64_t hash, G1StringDedupEntry** list) { +void G1StringDedupTable::add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list) { G1StringDedupEntry* entry = _entry_cache->alloc(); entry->set_obj(value); - if (use_java_hash()) { - entry->set_java_hash((unsigned int)hash); - } else { - entry->set_alt_hash(hash); - } + entry->set_hash(hash); entry->set_next(*list); *list = entry; _entries++; @@ -259,7 +255,7 @@ void G1StringDedupTable::transfer(G1StringDedupEntry** pentry, G1StringDedupTable* dest) { G1StringDedupEntry* entry = *pentry; *pentry = entry->next(); - uint64_t hash = use_java_hash() ? entry->java_hash() : entry->alt_hash(); + unsigned int hash = entry->hash(); size_t index = dest->hash_to_index(hash); G1StringDedupEntry** list = dest->bucket(index); entry->set_next(*list); @@ -274,10 +270,10 @@ value1->length() * sizeof(jchar))))); } -typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, uint64_t hash, +typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list, uintx &count) { for (G1StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) { - if ((use_java_hash() ? entry->java_hash() : entry->alt_hash()) == hash) { + if (entry->hash() == hash) { typeArrayOop existing_value = entry->obj(); if (equals(value, existing_value)) { // Match found @@ -291,7 +287,7 @@ return NULL; } -typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, uint64_t hash) { +typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, unsigned int hash) { size_t index = hash_to_index(hash); G1StringDedupEntry** list = bucket(index); uintx count = 0; @@ -315,25 +311,19 @@ return existing_value; } -unsigned int G1StringDedupTable::java_hash_code(typeArrayOop value) { - assert(use_java_hash(), "Should not use java hash code"); +unsigned int G1StringDedupTable::hash_code(typeArrayOop value) { unsigned int hash; int length = value->length(); const jchar* data = (jchar*)value->base(T_CHAR); - hash = java_lang_String::hash_code(data, length); - + if (use_java_hash()) { + hash = java_lang_String::hash_code(data, length); + } else { + hash = AltHashing::halfsiphash_32(_table->_hash_seed, (const uint16_t*)data, length); + } return hash; } -uint64_t G1StringDedupTable::alt_hash_code(typeArrayOop value) { - assert(!use_java_hash(), "Should not use alt hash code"); - - int length = value->length(); - const jbyte* data = (jbyte*)value->base(T_BYTE); - return AltHashing::halfsiphash_64(_table->_hash_seed, (const int8_t*)data, length); -} - void G1StringDedupTable::deduplicate(oop java_string, G1StringDedupStat& stat) { assert(java_lang_String::is_instance(java_string), "Must be a string"); No_Safepoint_Verifier nsv; @@ -347,7 +337,7 @@ return; } - uint64_t hash = 0; + unsigned int hash = 0; if (use_java_hash()) { // Get hash code from cache @@ -356,7 +346,7 @@ if (hash == 0) { // Compute hash - hash = alt_hash_code(value); + hash = hash_code(value); stat.inc_hashed(); } @@ -510,9 +500,8 @@ // destination partitions. finish_rehash() will do a single // threaded transfer of all entries. typeArrayOop value = (typeArrayOop)*p; - assert(!use_java_hash(), "Should not be using Java hash"); - uint64_t hash = alt_hash_code(value); - (*entry)->set_alt_hash(hash); + unsigned int hash = hash_code(value); + (*entry)->set_hash(hash); } // Move to next entry @@ -575,14 +564,8 @@ guarantee(Universe::heap()->is_in_reserved(value), "Object must be on the heap"); guarantee(!value->is_forwarded(), "Object must not be forwarded"); guarantee(value->is_typeArray(), "Object must be a typeArrayOop"); - uint64_t hash; - if (use_java_hash()) { - hash = (*entry)->java_hash(); - guarantee(java_hash_code(value) == hash, "Table entry has incorrect hash"); - } else { - hash = (*entry)->alt_hash(); - guarantee(alt_hash_code(value) == hash, "Table entry has incorrect hash"); - } + unsigned int hash = hash_code(value); + guarantee((*entry)->hash() == hash, "Table entry has inorrect hash"); guarantee(_table->hash_to_index(hash) == bucket, "Table entry has incorrect index"); entry = (*entry)->next_addr(); } @@ -597,10 +580,7 @@ G1StringDedupEntry** entry2 = (*entry1)->next_addr(); while (*entry2 != NULL) { typeArrayOop value2 = (*entry2)->obj(); - guarantee(value1 != value2, "Table entries must not have the same array"); - if (use_java_hash()) { - guarantee(!equals(value1, value2), "Table entries must not have identical arrays"); - } + guarantee(!equals(value1, value2), "Table entries must not have identical arrays"); entry2 = (*entry2)->next_addr(); } entry1 = (*entry1)->next_addr(); @@ -619,7 +599,7 @@ " [Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT "]\n" " [Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT "]\n" " [Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")]\n" - " [Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: " UINT64_FORMAT_X "]\n" + " [Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: " UINT64_FORMAT "]\n" " [Age Threshold: " UINTX_FORMAT "]", G1_STRDEDUP_BYTES_PARAM(_table->_size * sizeof(G1StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(G1StringDedupEntry)), _table->_size, _min_size, _max_size,
--- a/src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp Wed Sep 23 15:18:53 2020 +0300 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp Wed Sep 23 16:26:20 2020 +0300 @@ -38,11 +38,9 @@ class G1StringDedupEntry : public CHeapObj<mtGC> { private: G1StringDedupEntry* _next; - uint64_t _hash; + unsigned int _hash; typeArrayOop _obj; - static const uint64_t java_hash_mask = ((uint64_t)1 << 32) - 1; - public: G1StringDedupEntry() : _next(NULL), @@ -62,19 +60,11 @@ _next = next; } - unsigned int java_hash() { - return (unsigned int)(_hash & java_hash_mask); - } - - void set_java_hash(unsigned int hash) { - _hash = hash; - } - - uint64_t alt_hash() { + unsigned int hash() { return _hash; } - void set_alt_hash(uint64_t hash) { + void set_hash(unsigned int hash) { _hash = hash; } @@ -129,7 +119,7 @@ // The hash seed also dictates which hash function to use. A // zero hash seed means we will use the Java compatible hash // function (which doesn't use a seed), and a non-zero hash - // seed means we use the alternate and better hash function. + // seed means we use the murmur3 and better hash function. uint64_t _hash_seed; // Constants governing table resize/rehash/cache. @@ -156,12 +146,12 @@ } // Returns the hash bucket index for the given hash code. - size_t hash_to_index(uint64_t hash) { + size_t hash_to_index(unsigned int hash) { return (size_t)hash & (_size - 1); } // Adds a new table entry to the given hash bucket. - void add(typeArrayOop value, uint64_t hash, G1StringDedupEntry** list); + void add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list); // Removes the given table entry from the table. void remove(G1StringDedupEntry** pentry, uint worker_id); @@ -171,15 +161,15 @@ // Returns an existing character array in the given hash bucket, or NULL // if no matching character array exists. - typeArrayOop lookup(typeArrayOop value, uint64_t hash, + typeArrayOop lookup(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list, uintx &count); // Returns an existing character array in the table, or inserts a new // table entry if no matching character array exists. - typeArrayOop lookup_or_add_inner(typeArrayOop value, uint64_t hash); + typeArrayOop lookup_or_add_inner(typeArrayOop value, unsigned int hash); // Thread safe lookup or add of table entry - static typeArrayOop lookup_or_add(typeArrayOop value, uint64_t hash) { + static typeArrayOop lookup_or_add(typeArrayOop value, unsigned int hash) { // Protect the table from concurrent access. Also note that this lock // acts as a fence for _table, which could have been replaced by a new // instance if the table was resized or rehashed. @@ -197,8 +187,7 @@ // Computes the hash code for the given character array, using the // currently active hash function and hash seed. - static unsigned int java_hash_code(typeArrayOop value); - static uint64_t alt_hash_code(typeArrayOop value); + static unsigned int hash_code(typeArrayOop value); static uintx unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, size_t partition_begin,
--- a/src/share/vm/memory/filemap.cpp Wed Sep 23 15:18:53 2020 +0300 +++ b/src/share/vm/memory/filemap.cpp Wed Sep 23 16:26:20 2020 +0300 @@ -125,13 +125,13 @@ } else { // Get the hash value. Use a static seed because the hash needs to return the same // value over multiple jvm invocations. - uint64_t hash = AltHashing::halfsiphash_64(8191, (const int8_t*)vm_version, version_len); + uint32_t hash = AltHashing::halfsiphash_32(8191, (const uint8_t*)vm_version, version_len); - // Truncate the ident, saving room for the 16 hex character hash value. - strncpy(header_version, vm_version, JVM_IDENT_MAX-17); + // Truncate the ident, saving room for the 8 hex character hash value. + strncpy(header_version, vm_version, JVM_IDENT_MAX-9); - // Append the hash code as 16 hex digits. - sprintf(&header_version[JVM_IDENT_MAX-17], "%016" PRIx64, hash); + // Append the hash code as eight hex digits. + sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash); header_version[JVM_IDENT_MAX-1] = 0; // Null terminate. } }
--- a/src/share/vm/oops/oop.cpp Wed Sep 23 15:18:53 2020 +0300 +++ b/src/share/vm/oops/oop.cpp Wed Sep 23 16:26:20 2020 +0300 @@ -111,7 +111,7 @@ jchar* chars = java_lang_String::as_unicode_string(this, length, THREAD); if (chars != NULL) { // Use alternate hashing algorithm on the string - return AltHashing::halfsiphash_64(seed, chars, length); + return AltHashing::halfsiphash_32(seed, chars, length); } else { vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode strings for String table rehash"); return 0;
--- a/src/share/vm/oops/symbol.cpp Wed Sep 23 15:18:53 2020 +0300 +++ b/src/share/vm/oops/symbol.cpp Wed Sep 23 16:26:20 2020 +0300 @@ -210,7 +210,7 @@ unsigned int Symbol::new_hash(juint seed) { ResourceMark rm; // Use alternate hashing algorithm on this symbol. - return AltHashing::halfsiphash_64(seed, (const int8_t*)as_C_string(), utf8_length()); + return AltHashing::halfsiphash_32(seed, (const uint8_t*)as_C_string(), utf8_length()); } void Symbol::increment_refcount() {