< prev index next >

src/hotspot/share/classfile/stringTable.cpp

Print this page

        

*** 28,46 **** #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/oopStorage.inline.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" - #include "oops/compressedOops.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" #include "oops/weakHandle.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" --- 28,46 ---- #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/oopStorage.inline.hpp" + #include "gc/shared/oopStorageParState.inline.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" #include "oops/weakHandle.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp"
*** 76,100 **** java_lang_String::equals > _shared_table; #endif // -------------------------------------------------------------------------- - typedef ConcurrentHashTable<WeakHandle<vm_string_table_data>, - StringTableConfig, mtSymbol> StringTableHash; - static StringTableHash* _local_table = NULL; - - volatile bool StringTable::_has_work = false; - volatile bool StringTable::_needs_rehashing = false; - - volatile size_t StringTable::_uncleaned_items_count = 0; - OopStorage* StringTable::_weak_handles = NULL; - - static size_t _current_size = 0; - static volatile size_t _items_count = 0; - - volatile bool _alt_hash = false; static juint murmur_seed = 0; uintx hash_string(const jchar* s, int len, bool useAlt) { return useAlt ? AltHashing::murmur3_32(murmur_seed, s, len) : --- 76,88 ---- java_lang_String::equals > _shared_table; #endif // -------------------------------------------------------------------------- + StringTable* StringTable::_the_table = NULL; + volatile bool StringTable::_alt_hash = false; static juint murmur_seed = 0; uintx hash_string(const jchar* s, int len, bool useAlt) { return useAlt ? AltHashing::murmur3_32(murmur_seed, s, len) :
*** 116,126 **** ResourceMark rm(THREAD); // All String oops are hashed as unicode int length; jchar* chars = java_lang_String::as_unicode_string(val_oop, length, THREAD); if (chars != NULL) { ! return hash_string(chars, length, _alt_hash); } vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "get hash from oop"); return 0; } // We use default allocation/deallocation but counted --- 104,114 ---- ResourceMark rm(THREAD); // All String oops are hashed as unicode int length; jchar* chars = java_lang_String::as_unicode_string(val_oop, length, THREAD); if (chars != NULL) { ! return hash_string(chars, length, StringTable::_alt_hash); } vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "get hash from oop"); return 0; } // We use default allocation/deallocation but counted
*** 205,256 **** size_t ret; for (ret = 1; ((size_t)1 << ret) < val; ++ret); return ret; } ! void StringTable::create_table() { _weak_handles = new OopStorage("StringTable weak", StringTableWeakAlloc_lock, StringTableWeakActive_lock); size_t start_size_log_2 = ceil_log2(StringTableSize); _current_size = ((size_t)1) << start_size_log_2; log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", _current_size, start_size_log_2); _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN); } size_t StringTable::item_added() { ! return Atomic::add((size_t)1, &_items_count); } size_t StringTable::add_items_to_clean(size_t ndead) { ! size_t total = Atomic::add((size_t)ndead, &_uncleaned_items_count); log_trace(stringtable)( "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT, ! _uncleaned_items_count, ndead, total); return total; } void StringTable::item_removed() { ! Atomic::add((size_t)-1, &_items_count); } ! double StringTable::get_load_factor() { return (double)_items_count/_current_size; } ! double StringTable::get_dead_factor() { return (double)_uncleaned_items_count/_current_size; } size_t StringTable::table_size() { return ((size_t)1) << _local_table->get_size_log2(Thread::current()); } void StringTable::trigger_concurrent_work() { ! MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); ! _has_work = true; Service_lock->notify_all(); } // Probing oop StringTable::lookup(Symbol* symbol) { --- 193,251 ---- size_t ret; for (ret = 1; ((size_t)1 << ret) < val; ++ret); return ret; } ! StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0), ! _needs_rehashing(false), _weak_handles(NULL), _items_count(0), _uncleaned_items_count(0) { _weak_handles = new OopStorage("StringTable weak", StringTableWeakAlloc_lock, StringTableWeakActive_lock); size_t start_size_log_2 = ceil_log2(StringTableSize); _current_size = ((size_t)1) << start_size_log_2; log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", _current_size, start_size_log_2); _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN); } + void StringTable::update_needs_rehash(bool rehash) { + if (rehash) { + _needs_rehashing = true; + } + } + size_t StringTable::item_added() { ! return Atomic::add((size_t)1, &(the_table()->_items_count)); } size_t StringTable::add_items_to_clean(size_t ndead) { ! size_t total = Atomic::add((size_t)ndead, &(the_table()->_uncleaned_items_count)); log_trace(stringtable)( "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT, ! the_table()->_uncleaned_items_count, ndead, total); return total; } void StringTable::item_removed() { ! Atomic::add((size_t)-1, &(the_table()->_items_count)); } ! double StringTable::get_load_factor() const { return (double)_items_count/_current_size; } ! double StringTable::get_dead_factor() const { return (double)_uncleaned_items_count/_current_size; } size_t StringTable::table_size() { return ((size_t)1) << _local_table->get_size_log2(Thread::current()); } void StringTable::trigger_concurrent_work() { ! MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); ! the_table()->_has_work = true; Service_lock->notify_all(); } // Probing oop StringTable::lookup(Symbol* symbol) {
*** 260,277 **** return lookup(chars, length); } oop StringTable::lookup(const jchar* name, int len) { unsigned int hash = java_lang_String::hash_code(name, len); ! oop string = lookup_shared(name, len, hash); if (string != NULL) { return string; } ! if (_alt_hash) { hash = hash_string(name, len, true); } ! return do_lookup(name, len, hash); } class StringTableGet : public StackObj { Thread* _thread; Handle _return; --- 255,272 ---- return lookup(chars, length); } oop StringTable::lookup(const jchar* name, int len) { unsigned int hash = java_lang_String::hash_code(name, len); ! oop string = StringTable::the_table()->lookup_shared(name, len, hash); if (string != NULL) { return string; } ! if (StringTable::_alt_hash) { hash = hash_string(name, len, true); } ! return StringTable::the_table()->do_lookup(name, len, hash); } class StringTableGet : public StackObj { Thread* _thread; Handle _return;
*** 331,352 **** } oop StringTable::intern(Handle string_or_null_h, const jchar* name, int len, TRAPS) { // shared table always uses java_lang_String::hash_code unsigned int hash = java_lang_String::hash_code(name, len); ! oop found_string = lookup_shared(name, len, hash); if (found_string != NULL) { return found_string; } ! if (_alt_hash) { hash = hash_string(name, len, true); } ! found_string = do_lookup(name, len, hash); if (found_string != NULL) { return found_string; } ! return do_intern(string_or_null_h, name, len, hash, CHECK_NULL); } oop StringTable::do_intern(Handle string_or_null_h, const jchar* name, int len, uintx hash, TRAPS) { HandleMark hm(THREAD); // cleanup strings created --- 326,348 ---- } oop StringTable::intern(Handle string_or_null_h, const jchar* name, int len, TRAPS) { // shared table always uses java_lang_String::hash_code unsigned int hash = java_lang_String::hash_code(name, len); ! oop found_string = StringTable::the_table()->lookup_shared(name, len, hash); if (found_string != NULL) { return found_string; } ! if (StringTable::_alt_hash) { hash = hash_string(name, len, true); } ! found_string = StringTable::the_table()->do_lookup(name, len, hash); if (found_string != NULL) { return found_string; } ! return StringTable::the_table()->do_intern(string_or_null_h, name, len, ! hash, CHECK_NULL); } oop StringTable::do_intern(Handle string_or_null_h, const jchar* name, int len, uintx hash, TRAPS) { HandleMark hm(THREAD); // cleanup strings created
*** 370,398 **** StringTableLookupOop lookup(THREAD, hash, string_h); StringTableGet stg(THREAD); bool rehash_warning; do { ! // Callers have already looked up the String using the jchar* name, so just go to add. WeakHandle<vm_string_table_data> wh = WeakHandle<vm_string_table_data>::create(string_h); // The hash table takes ownership of the WeakHandle, even if it's not inserted. if (_local_table->insert(THREAD, lookup, wh, &rehash_warning)) { update_needs_rehash(rehash_warning); return wh.resolve(); } - // In case another thread did a concurrent add, return value already in the table. - // This could fail if the String got gc'ed concurrently, so loop back until success. - if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) { - update_needs_rehash(rehash_warning); - return stg.get_res_oop(); - } } while(true); } void StringTable::oops_do(OopClosure* f) { assert(f != NULL, "No closure"); ! _weak_handles->oops_do(f); } // Concurrent work void StringTable::grow(JavaThread* jt) { StringTableHash::GrowTask gt(_local_table); --- 366,399 ---- StringTableLookupOop lookup(THREAD, hash, string_h); StringTableGet stg(THREAD); bool rehash_warning; do { ! if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) { ! update_needs_rehash(rehash_warning); ! return stg.get_res_oop(); ! } WeakHandle<vm_string_table_data> wh = WeakHandle<vm_string_table_data>::create(string_h); // The hash table takes ownership of the WeakHandle, even if it's not inserted. if (_local_table->insert(THREAD, lookup, wh, &rehash_warning)) { update_needs_rehash(rehash_warning); return wh.resolve(); } } while(true); } void StringTable::oops_do(OopClosure* f) { assert(f != NULL, "No closure"); ! StringTable::the_table()->_weak_handles->oops_do(f); ! } ! ! void StringTable::possibly_parallel_oops_do( ! OopStorage::ParState<false /* concurrent */, false /* const */>* ! _par_state_string, OopClosure* f) ! { ! assert(f != NULL, "No closure"); ! _par_state_string->oops_do(f); } // Concurrent work void StringTable::grow(JavaThread* jt) { StringTableHash::GrowTask gt(_local_table);
*** 476,486 **** load_factor, dead_factor); trigger_concurrent_work(); } } ! void StringTable::do_concurrent_work(JavaThread* jt) { _has_work = false; double load_factor = get_load_factor(); log_debug(stringtable, perf)("Concurrent work, live factor: %g", load_factor); // We prefer growing, since that also removes dead items if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { --- 477,487 ---- load_factor, dead_factor); trigger_concurrent_work(); } } ! void StringTable::concurrent_work(JavaThread* jt) { _has_work = false; double load_factor = get_load_factor(); log_debug(stringtable, perf)("Concurrent work, live factor: %g", load_factor); // We prefer growing, since that also removes dead items if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {
*** 488,497 **** --- 489,502 ---- } else { clean_dead_entries(jt); } } + void StringTable::do_concurrent_work(JavaThread* jt) { + StringTable::the_table()->concurrent_work(jt); + } + // Rehash bool StringTable::do_rehash() { if (!_local_table->is_safepoint_safe()) { return false; }
*** 511,521 **** _local_table = new_table; return true; } ! void StringTable::rehash_table() { static bool rehashed = false; log_debug(stringtable)("Table imbalanced, rehashing called."); // Grow instead of rehash. if (get_load_factor() > PREF_AVG_LIST_LEN && --- 516,526 ---- _local_table = new_table; return true; } ! void StringTable::try_rehash_table() { static bool rehashed = false; log_debug(stringtable)("Table imbalanced, rehashing called."); // Grow instead of rehash. if (get_load_factor() > PREF_AVG_LIST_LEN &&
*** 542,551 **** --- 547,560 ---- } } _needs_rehashing = false; } + void StringTable::rehash_table() { + StringTable::the_table()->try_rehash_table(); + } + // Statistics static int literal_size(oop obj) { // NOTE: this would over-count if (pre-JDK8) // java_lang_Class::has_offset_field() is true and the String.value array is // shared by several Strings. However, starting from JDK8, the String.value
*** 568,584 **** } return literal_size(s); }; }; - TableStatistics StringTable::get_table_statistics() { - static TableStatistics ts; - SizeFunc sz; - ts = _local_table->statistics_get(Thread::current(), sz, ts); - return ts; - } - void StringTable::print_table_statistics(outputStream* st, const char* table_name) { SizeFunc sz; _local_table->statistics_to(Thread::current(), sz, st, table_name); } --- 577,586 ----
*** 597,607 **** // This verification is part of Universe::verify() and needs to be quick. void StringTable::verify() { Thread* thr = Thread::current(); VerifyStrings vs; ! if (!_local_table->try_scan(thr, vs)) { log_info(stringtable)("verify unavailable at this moment"); } } // Verification and comp --- 599,609 ---- // This verification is part of Universe::verify() and needs to be quick. void StringTable::verify() { Thread* thr = Thread::current(); VerifyStrings vs; ! if (!the_table()->_local_table->try_scan(thr, vs)) { log_info(stringtable)("verify unavailable at this moment"); } } // Verification and comp
*** 630,643 **** size_t StringTable::verify_and_compare_entries() { Thread* thr = Thread::current(); GrowableArray<oop>* oops = new (ResourceObj::C_HEAP, mtInternal) ! GrowableArray<oop>((int)_current_size, true); VerifyCompStrings vcs(oops); ! if (!_local_table->try_scan(thr, vcs)) { log_info(stringtable)("verify unavailable at this moment"); } delete oops; return vcs._errors; } --- 632,645 ---- size_t StringTable::verify_and_compare_entries() { Thread* thr = Thread::current(); GrowableArray<oop>* oops = new (ResourceObj::C_HEAP, mtInternal) ! GrowableArray<oop>((int)the_table()->_current_size, true); VerifyCompStrings vcs(oops); ! if (!the_table()->_local_table->try_scan(thr, vcs)) { log_info(stringtable)("verify unavailable at this moment"); } delete oops; return vcs._errors; }
*** 680,696 **** }; }; void StringTable::dump(outputStream* st, bool verbose) { if (!verbose) { ! print_table_statistics(st, "StringTable"); } else { Thread* thr = Thread::current(); ResourceMark rm(thr); st->print_cr("VERSION: 1.1"); PrintString ps(thr, st); ! if (!_local_table->try_scan(thr, ps)) { st->print_cr("dump unavailable at this moment"); } } } --- 682,698 ---- }; }; void StringTable::dump(outputStream* st, bool verbose) { if (!verbose) { ! the_table()->print_table_statistics(st, "StringTable"); } else { Thread* thr = Thread::current(); ResourceMark rm(thr); st->print_cr("VERSION: 1.1"); PrintString ps(thr, st); ! if (!the_table()->_local_table->try_scan(thr, ps)) { st->print_cr("dump unavailable at this moment"); } } }
*** 757,766 **** --- 759,770 ---- oop s = val->peek(); if (s == NULL) { return true; } unsigned int hash = java_lang_String::hash_code(s); + + java_lang_String::set_hash(s, hash); oop new_s = StringTable::create_archived_string(s, Thread::current()); if (new_s == NULL) { return true; }
*** 773,790 **** void StringTable::copy_shared_string_table(CompactHashtableWriter* writer) { assert(HeapShared::is_heap_object_archiving_allowed(), "must be"); CopyToArchive copy(writer); ! _local_table->do_safepoint_scan(copy); } void StringTable::write_to_archive() { assert(HeapShared::is_heap_object_archiving_allowed(), "must be"); _shared_table.reset(); ! CompactHashtableWriter writer(_items_count, &MetaspaceShared::stats()->string); // Copy the interned strings into the "string space" within the java heap copy_shared_string_table(&writer); writer.dump(&_shared_table, "string"); } --- 777,797 ---- void StringTable::copy_shared_string_table(CompactHashtableWriter* writer) { assert(HeapShared::is_heap_object_archiving_allowed(), "must be"); CopyToArchive copy(writer); ! StringTable::the_table()->_local_table->do_safepoint_scan(copy); } void StringTable::write_to_archive() { assert(HeapShared::is_heap_object_archiving_allowed(), "must be"); _shared_table.reset(); ! int num_buckets = CompactHashtableWriter::default_num_buckets( ! StringTable::the_table()->_items_count); ! CompactHashtableWriter writer(num_buckets, ! &MetaspaceShared::stats()->string); // Copy the interned strings into the "string space" within the java heap copy_shared_string_table(&writer); writer.dump(&_shared_table, "string"); }
< prev index next >