--- old/src/hotspot/share/classfile/stringTable.cpp 2018-06-11 15:58:41.523486653 +0200 +++ new/src/hotspot/share/classfile/stringTable.cpp 2018-06-11 15:58:41.315479504 +0200 @@ -198,17 +198,16 @@ return Atomic::add((size_t)1, &(the_table()->_items)); } -size_t StringTable::items_to_clean(size_t ncl) { - size_t total = Atomic::add((size_t)ncl, &(the_table()->_uncleaned_items)); +size_t StringTable::add_items_to_clean(size_t ndead) { + size_t total = Atomic::add((size_t)ndead, &(the_table()->_uncleaned_items)); log_trace(stringtable)( "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT, - the_table()->_uncleaned_items, ncl, total); + the_table()->_uncleaned_items, ndead, total); return total; } void StringTable::item_removed() { Atomic::add((size_t)-1, &(the_table()->_items)); - Atomic::add((size_t)-1, &(the_table()->_uncleaned_items)); } double StringTable::get_load_factor() { @@ -405,8 +404,11 @@ StringTable::the_table()->_weak_handles->weak_oops_do(&stiac, tmp); - StringTable::the_table()->items_to_clean(stiac._count); + // This is the serial case without ParState. + // Just set the correct number and check for a cleaning phase. + the_table()->_uncleaned_items = stiac._count; StringTable::the_table()->check_concurrent_work(); + if (processed != NULL) { *processed = (int) stiac._count_total; } @@ -430,8 +432,9 @@ _par_state_string->weak_oops_do(&stiac, &dnc); - StringTable::the_table()->items_to_clean(stiac._count); - StringTable::the_table()->check_concurrent_work(); + // Accumulate the dead strings. + the_table()->add_items_to_clean(stiac._count); + *processed = (int) stiac._count_total; *removed = (int) stiac._count; } @@ -467,10 +470,8 @@ } struct StringTableDoDelete : StackObj { - long _count; - StringTableDoDelete() : _count(0) {} void operator()(WeakHandle* val) { - ++_count; + /* do nothing */ } }; @@ -524,6 +525,7 @@ if (_has_work) { return; } + double load_factor = StringTable::get_load_factor(); double dead_factor = StringTable::get_dead_factor(); // We should clean/resize if we have more dead than alive, --- old/src/hotspot/share/classfile/stringTable.hpp 2018-06-11 15:58:42.426517688 +0200 +++ new/src/hotspot/share/classfile/stringTable.hpp 2018-06-11 15:58:42.220510608 +0200 @@ -83,7 +83,7 @@ static uintx item_added(); static void item_removed(); - static size_t items_to_clean(size_t ncl); + size_t add_items_to_clean(size_t ndead); StringTable(); @@ -113,6 +113,23 @@ static bool has_work() { return the_table()->_has_work; } // GC support + + // Must be called before a parallel walk where strings might die. + static void reset_dead_counter() { + the_table()->_uncleaned_items = 0; + } + // After the parallel walk this method must be called to trigger + // cleaning. Note it might trigger a resize instead. + static void finish_dead_counter() { + the_table()->check_concurrent_work(); + } + + // If GC uses ParState directly it should add the number of cleared + // string to this method. + static void inc_dead_counter(size_t ndead) { + the_table()->add_items_to_clean(ndead); + } + // Delete pointers to otherwise-unreachable objects. static void unlink(BoolObjectClosure* cl) { unlink_or_oops_do(cl); @@ -150,9 +167,9 @@ oop lookup_shared(jchar* name, int len, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(NULL); static void copy_shared_string_table(CompactStringTableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN; public: - static oop create_archived_string(oop s, Thread* THREAD); + static oop create_archived_string(oop s, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL); static void set_shared_string_mapped() { _shared_string_mapped = true; } - static bool shared_string_mapped() { return _shared_string_mapped; } + static bool shared_string_mapped() { return _shared_string_mapped; } static void shared_oops_do(OopClosure* f) NOT_CDS_JAVA_HEAP_RETURN; static void write_to_archive() NOT_CDS_JAVA_HEAP_RETURN; static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; --- old/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp 2018-06-11 15:58:43.278546970 +0200 +++ new/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp 2018-06-11 15:58:43.066539684 +0200 @@ -2775,7 +2775,12 @@ AbstractGangTask(name), _collector(collector), _n_workers(n_workers), - _par_state_string(StringTable::weak_storage()) {} + _par_state_string(StringTable::weak_storage()) { + StringTable::reset_dead_counter(); + } + ~CMSParMarkTask() { + StringTable::finish_dead_counter(); + } // Work method in support of parallel rescan ... of young gen spaces void do_young_space_rescan(OopsInGenClosure* cl, ContiguousSpace* space, --- old/src/hotspot/share/gc/cms/parNewGeneration.cpp 2018-06-11 15:58:44.385585016 +0200 +++ new/src/hotspot/share/gc/cms/parNewGeneration.cpp 2018-06-11 15:58:44.090574877 +0200 @@ -591,8 +591,13 @@ _young_old_boundary(young_old_boundary), _state_set(state_set), _strong_roots_scope(strong_roots_scope), - _par_state_string(StringTable::weak_storage()) -{} + _par_state_string(StringTable::weak_storage()) { + StringTable::reset_dead_counter(); +} + +ParNewGenTask::~ParNewGenTask() { + StringTable::finish_dead_counter(); +} void ParNewGenTask::work(uint worker_id) { CMSHeap* heap = CMSHeap::heap(); --- old/src/hotspot/share/gc/cms/parNewGeneration.hpp 2018-06-11 15:58:45.295616292 +0200 +++ new/src/hotspot/share/gc/cms/parNewGeneration.hpp 2018-06-11 15:58:45.084609040 +0200 @@ -245,6 +245,7 @@ HeapWord* young_old_boundary, ParScanThreadStateSet* state_set, StrongRootsScope* strong_roots_scope); + ~ParNewGenTask(); HeapWord* young_old_boundary() { return _young_old_boundary; } --- old/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 2018-06-11 15:58:46.229648392 +0200 +++ new/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 2018-06-11 15:58:46.018641140 +0200 @@ -3249,6 +3249,9 @@ if (process_symbols) { SymbolTable::clear_parallel_claimed_index(); } + if (process_strings) { + StringTable::reset_dead_counter(); + } } ~G1StringAndSymbolCleaningTask() { @@ -3262,6 +3265,9 @@ "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed", strings_processed(), strings_removed(), symbols_processed(), symbols_removed()); + if (_process_strings) { + StringTable::finish_dead_counter(); + } } void work(uint worker_id) { --- old/src/hotspot/share/gc/g1/g1RootProcessor.cpp 2018-06-11 15:58:47.122679083 +0200 +++ new/src/hotspot/share/gc/g1/g1RootProcessor.cpp 2018-06-11 15:58:46.915671969 +0200 @@ -74,7 +74,13 @@ _srs(n_workers), _lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never), _par_state_string(StringTable::weak_storage()), - _n_workers_discovered_strong_classes(0) {} + _n_workers_discovered_strong_classes(0) { + StringTable::reset_dead_counter(); +} + +G1RootProcessor::~G1RootProcessor() { + StringTable::finish_dead_counter(); +} void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) { G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times(); --- old/src/hotspot/share/gc/g1/g1RootProcessor.hpp 2018-06-11 15:58:47.949707506 +0200 +++ new/src/hotspot/share/gc/g1/g1RootProcessor.hpp 2018-06-11 15:58:47.745700495 +0200 @@ -99,6 +99,7 @@ public: G1RootProcessor(G1CollectedHeap* g1h, uint n_workers); + ~G1RootProcessor(); // Apply correct closures from pss to the strongly and weakly reachable roots in the system // in a single pass. --- old/src/hotspot/share/gc/z/zRootsIterator.cpp 2018-06-11 15:58:48.787736307 +0200 +++ new/src/hotspot/share/gc/z/zRootsIterator.cpp 2018-06-11 15:58:48.578729124 +0200 @@ -307,10 +307,12 @@ assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); ZStatTimer timer(ZSubPhasePauseWeakRootsSetup); SymbolTable::clear_parallel_claimed_index(); + StringTable::reset_dead_counter(); } ZWeakRootsIterator::~ZWeakRootsIterator() { ZStatTimer timer(ZSubPhasePauseWeakRootsTeardown); + StringTable::finish_dead_counter(); } void ZWeakRootsIterator::do_vm_weak_handles(BoolObjectClosure* is_alive, OopClosure* cl) { @@ -341,9 +343,34 @@ SymbolTable::possibly_parallel_unlink(&dummy, &dummy); } +class ZStringTableDeadCounterBoolObjectClosure : public BoolObjectClosure { +private: + BoolObjectClosure* const _cl; + size_t _ndead; + +public: + ZStringTableDeadCounterBoolObjectClosure(BoolObjectClosure* cl) : + _cl(cl), + _ndead(0) {} + + ~ZStringTableDeadCounterBoolObjectClosure() { + StringTable::inc_dead_counter(_ndead); + } + + virtual bool do_object_b(oop obj) { + if (_cl->do_object_b(obj)) { + return true; + } + + _ndead++; + return false; + } +}; + void ZWeakRootsIterator::do_string_table(BoolObjectClosure* is_alive, OopClosure* cl) { ZStatTimer timer(ZSubPhasePauseWeakRootsStringTable); - _string_table_iter.weak_oops_do(is_alive, cl); + ZStringTableDeadCounterBoolObjectClosure counter_is_alive(is_alive); + _string_table_iter.weak_oops_do(&counter_is_alive, cl); } void ZWeakRootsIterator::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* cl) { @@ -377,7 +404,13 @@ _string_table_iter(StringTable::weak_storage()), _vm_weak_handles(this), _jni_weak_handles(this), - _string_table(this) {} + _string_table(this) { + StringTable::reset_dead_counter(); +} + +ZConcurrentWeakRootsIterator::~ZConcurrentWeakRootsIterator() { + StringTable::finish_dead_counter(); +} void ZConcurrentWeakRootsIterator::do_vm_weak_handles(OopClosure* cl) { ZStatTimer timer(ZSubPhaseConcurrentWeakRootsVMWeakHandles); @@ -389,9 +422,36 @@ _jni_weak_handles_iter.oops_do(cl); } +class ZStringTableDeadCounterOopClosure : public OopClosure { +private: + OopClosure* const _cl; + size_t _ndead; + +public: + ZStringTableDeadCounterOopClosure(OopClosure* cl) : + _cl(cl), + _ndead(0) {} + + ~ZStringTableDeadCounterOopClosure() { + StringTable::inc_dead_counter(_ndead); + } + + virtual void do_oop(oop* p) { + _cl->do_oop(p); + if (*p == NULL) { + _ndead++; + } + } + + virtual void do_oop(narrowOop* p) { + ShouldNotReachHere(); + } +}; + void ZConcurrentWeakRootsIterator::do_string_table(OopClosure* cl) { ZStatTimer timer(ZSubPhaseConcurrentWeakRootsStringTable); - _string_table_iter.oops_do(cl); + ZStringTableDeadCounterOopClosure counter_cl(cl); + _string_table_iter.oops_do(&counter_cl); } void ZConcurrentWeakRootsIterator::oops_do(OopClosure* cl) { --- old/src/hotspot/share/gc/z/zRootsIterator.hpp 2018-06-11 15:58:49.649765933 +0200 +++ new/src/hotspot/share/gc/z/zRootsIterator.hpp 2018-06-11 15:58:49.441758785 +0200 @@ -164,6 +164,7 @@ public: ZConcurrentWeakRootsIterator(); + ~ZConcurrentWeakRootsIterator(); void oops_do(OopClosure* cl); };