< prev index next >

src/share/vm/classfile/stringTable.cpp

Print this page

        

*** 36,45 **** --- 36,46 ---- #include "runtime/atomic.inline.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS + #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/g1StringDedup.hpp" #endif PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
*** 85,106 **** #endif // -------------------------------------------------------------------------- StringTable* StringTable::_the_table = NULL; ! bool StringTable::_needs_rehashing = false; volatile int StringTable::_parallel_claimed_idx = 0; // Pick hashing algorithm unsigned int StringTable::hash_string(const jchar* s, int len) { return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) : java_lang_String::hash_code(s, len); } ! oop StringTable::lookup(int index, jchar* name, int len, unsigned int hash) { int count = 0; for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) { count++; if (l->hash() == hash) { --- 86,116 ---- #endif // -------------------------------------------------------------------------- StringTable* StringTable::_the_table = NULL; ! bool StringTable::_ignore_shared_strings = false; bool StringTable::_needs_rehashing = false; volatile int StringTable::_parallel_claimed_idx = 0; + CompactHashtable<oop, char> StringTable::_shared_table; + // Pick hashing algorithm unsigned int StringTable::hash_string(const jchar* s, int len) { return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) : java_lang_String::hash_code(s, len); } ! oop StringTable::lookup_shared(jchar* name, int len) { ! // java_lang_String::hash_code() was used to compute hash values in the shared table. Don't ! // use the hash value from StringTable::hash_string() as it might use alternate hashcode. ! return _shared_table.lookup((const char*)name, ! java_lang_String::hash_code(name, len), len); ! } ! ! oop StringTable::lookup_dynamic(int index, jchar* name, int len, unsigned int hash) { int count = 0; for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) { count++; if (l->hash() == hash) {
*** 138,148 **** } // Since look-up was done lock-free, we need to check if another // thread beat us in the race to insert the symbol. ! oop test = lookup(index, name, len, hashValue); // calls lookup(u1*, int) if (test != NULL) { // Entry already added return test; } --- 148,159 ---- } // Since look-up was done lock-free, we need to check if another // thread beat us in the race to insert the symbol. ! // No need to lookup the shared table from here since the caller (intern()) already did ! oop test = lookup_dynamic(index, name, len, hashValue); // calls lookup(u1*, int) if (test != NULL) { // Entry already added return test; }
*** 170,194 **** } #endif } oop StringTable::lookup(jchar* name, int len) { unsigned int hash = hash_string(name, len); int index = the_table()->hash_to_index(hash); ! oop string = the_table()->lookup(index, name, len, hash); ensure_string_alive(string); return string; } oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS) { unsigned int hashValue = hash_string(name, len); int index = the_table()->hash_to_index(hashValue); ! oop found_string = the_table()->lookup(index, name, len, hashValue); // Found if (found_string != NULL) { ensure_string_alive(found_string); return found_string; --- 181,215 ---- } #endif } oop StringTable::lookup(jchar* name, int len) { + oop string = lookup_shared(name, len); + if (string != NULL) { + return string; + } + unsigned int hash = hash_string(name, len); int index = the_table()->hash_to_index(hash); ! string = the_table()->lookup_dynamic(index, name, len, hash); ensure_string_alive(string); return string; } oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS) { + oop found_string = lookup_shared(name, len); + if (found_string != NULL) { + return found_string; + } + unsigned int hashValue = hash_string(name, len); int index = the_table()->hash_to_index(hashValue); ! found_string = the_table()->lookup_dynamic(index, name, len, hashValue); // Found if (found_string != NULL) { ensure_string_alive(found_string); return found_string;
*** 609,613 **** --- 630,762 ---- return dcmd->_dcmdparser.num_arguments(); } else { return 0; } } + + // Sharing + bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space, + CompactHashtableWriter* ch_table) { + #if INCLUDE_CDS && INCLUDE_ALL_GCS && defined(_LP64) && !defined(_WINDOWS) + assert(UseG1GC, "Only support G1 GC"); + assert(UseCompressedOops && UseCompressedClassPointers, + "Only support UseCompressedOops and UseCompressedClassPointers enabled"); + + Thread* THREAD = Thread::current(); + G1CollectedHeap::heap()->begin_record_alloc_range(); + for (int i = 0; i < the_table()->table_size(); ++i) { + HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i); + for ( ; bucket != NULL; bucket = bucket->next()) { + oop s = (oop)(bucket->literal()); + unsigned int hash = java_lang_String::hash_code(s); + if (hash == 0) { + continue; + } + + // allocate the new 'value' array first + typeArrayOop v = java_lang_String::value(s); + int v_len = v->size(); + typeArrayOop new_v; + if (G1CollectedHeap::heap()->is_record_alloc_too_large(v_len)) { + continue; // skip the current String. The 'value' array is too large to handle + } else { + new_v = (typeArrayOop)G1CollectedHeap::heap()->record_mem_allocate(v_len); + if (new_v == NULL) { + return false; // allocation failed + } + } + // now allocate the new String object + int s_len = s->size(); + oop new_s = (oop)G1CollectedHeap::heap()->record_mem_allocate(s_len); + if (new_s == NULL) { + return false; + } + + s->identity_hash(); + v->identity_hash(); + + // copy the objects' data + Copy::aligned_disjoint_words((HeapWord*)s, (HeapWord*)new_s, s_len); + Copy::aligned_disjoint_words((HeapWord*)v, (HeapWord*)new_v, v_len); + + // adjust the pointer to the 'value' field in the new String oop. Also pre-compute and set the + // 'hash' field. That avoids "write" to the shared strings at runtime by the deduplication process. + java_lang_String::set_value_raw(new_s, new_v); + if (java_lang_String::hash(new_s) == 0) { + java_lang_String::set_hash(new_s, hash); + } + + // add to the compact table + ch_table->add(hash, new_s); + } + } + + G1CollectedHeap::heap()->end_record_alloc_range(string_space, os::vm_allocation_granularity()); + assert(string_space->length() <= 2, "sanity"); + #endif + return true; + } + + bool StringTable::copy_compact_table(char** top, char *end, GrowableArray<MemRegion> *string_space, + size_t* space_size) { + #if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS) + if (!(UseG1GC && UseCompressedOops && UseCompressedClassPointers)) { + if (PrintSharedSpaces) { + tty->print_cr("Shared strings are excluded from the archive as UseG1GC, " + "UseCompressedOops and UseCompressedClassPointers are required."); + } + return true; + } + + CompactHashtableWriter ch_table(CompactHashtable<oop, char>::_string_table, + the_table()->number_of_entries(), + &MetaspaceShared::stats()->string); + + // Copy the interned strings into the "string space" within the java heap + if (!copy_shared_string(string_space, &ch_table)) { + return false; + } + + for (int i = 0; i < string_space->length(); i++) { + *space_size += string_space->at(i).byte_size(); + } + + // Now dump the compact table + if (*top + ch_table.get_required_bytes() > end) { + // not enough space left + return false; + } + ch_table.dump(top, end); + *top = (char*)align_pointer_up(*top, sizeof(void*)); + + #endif + return true; + } + + void StringTable::shared_oops_do(OopClosure* f) { + #if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS) + _shared_table.oops_do(f); + #endif + } + + const char* StringTable::init_shared_table(FileMapInfo *mapinfo, char *buffer) { + #if INCLUDE_CDS && defined(_LP64) && !defined(_WINDOWS) + if (mapinfo->space_capacity(MetaspaceShared::first_string) == 0) { + // no shared string data + return buffer; + } + + // initialize the shared table + juint *p = (juint*)buffer; + const char* end = _shared_table.init( + CompactHashtable<oop, char>::_string_table, (char*)p); + const char* aligned_end = (const char*)align_pointer_up(end, sizeof(void*)); + + if (_ignore_shared_strings) { + _shared_table.reset(); + } + + return aligned_end; + #endif + + return buffer; + }
< prev index next >