diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index 8db4c08c966..d5abe096996 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -116,6 +116,8 @@ static size_t _current_size = 0; static volatile size_t _items_count = 0; volatile bool _alt_hash = false; + +static bool _rehashed = false; static uint64_t _alt_hash_seed = 0; uintx hash_string(const jchar* s, int len, bool useAlt) { @@ -529,20 +531,46 @@ bool StringTable::do_rehash() { return true; } +bool StringTable::should_grow() { + return get_load_factor() > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached(); +} + +bool StringTable::rehash_table_expects_safepoint_rehashing() { + // No rehashing required + if (!needs_rehashing()) { + return false; + } + + // Grow instead of rehash + if (should_grow()) { + return false; + } + + // Already rehashed + if (_rehashed) { + return false; + } + + // Resizing in progress + if (!_local_table->is_safepoint_safe()) { + return false; + } + + 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 && - !_local_table->is_max_size_reached()) { + if (should_grow()) { log_debug(stringtable)("Choosing growing over rehashing."); trigger_concurrent_work(); _needs_rehashing = false; return; } // Already rehashed. - if (rehashed) { + if (_rehashed) { log_warning(stringtable)("Rehashing already done, still long lists."); trigger_concurrent_work(); _needs_rehashing = false; @@ -552,7 +580,7 @@ void StringTable::rehash_table() { _alt_hash_seed = AltHashing::compute_seed(); { if (do_rehash()) { - rehashed = true; + _rehashed = true; } else { log_info(stringtable)("Resizes in progress rehashing skipped."); } diff --git a/src/hotspot/share/classfile/stringTable.hpp b/src/hotspot/share/classfile/stringTable.hpp index 44de539f53d..9549a8ce009 100644 --- a/src/hotspot/share/classfile/stringTable.hpp +++ b/src/hotspot/share/classfile/stringTable.hpp @@ -96,6 +96,11 @@ class StringTable : public CHeapObj{ static oop intern(const char *utf8_string, TRAPS); // Rehash the string table if it gets out of balance +private: + static bool should_grow(); + +public: + static bool rehash_table_expects_safepoint_rehashing(); static void rehash_table(); static bool needs_rehashing() { return _needs_rehashing; } static inline void update_needs_rehash(bool rehash) { diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index f277aa5f99d..61d5ba576b5 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -103,6 +103,7 @@ static THREAD_LOCAL bool _lookup_shared_first = false; // Static arena for symbols that are not deallocated Arena* SymbolTable::_arena = nullptr; +static bool _rehashed = false; static uint64_t _alt_hash_seed = 0; static inline void log_trace_symboltable_helper(Symbol* sym, const char* msg) { @@ -805,13 +806,39 @@ bool SymbolTable::do_rehash() { return true; } +bool SymbolTable::should_grow() { + return get_load_factor() > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached(); +} + +bool SymbolTable::rehash_table_expects_safepoint_rehashing() { + // No rehashing required + if (!needs_rehashing()) { + return false; + } + + // Grow instead of rehash + if (should_grow()) { + return false; + } + + // Already rehashed + if (_rehashed) { + return false; + } + + // Resizing in progress + if (!_local_table->is_safepoint_safe()) { + return false; + } + + return true; +} + void SymbolTable::rehash_table() { - static bool rehashed = false; log_debug(symboltable)("Table imbalanced, rehashing called."); // Grow instead of rehash. - if (get_load_factor() > PREF_AVG_LIST_LEN && - !_local_table->is_max_size_reached()) { + if (should_grow()) { log_debug(symboltable)("Choosing growing over rehashing."); trigger_cleanup(); _needs_rehashing = false; @@ -819,7 +846,7 @@ void SymbolTable::rehash_table() { } // Already rehashed. - if (rehashed) { + if (_rehashed) { log_warning(symboltable)("Rehashing already done, still long lists."); trigger_cleanup(); _needs_rehashing = false; @@ -829,7 +856,7 @@ void SymbolTable::rehash_table() { _alt_hash_seed = AltHashing::compute_seed(); if (do_rehash()) { - rehashed = true; + _rehashed = true; } else { log_info(symboltable)("Resizes in progress rehashing skipped."); } diff --git a/src/hotspot/share/classfile/symbolTable.hpp b/src/hotspot/share/classfile/symbolTable.hpp index d3d279987c0..282dd574c68 100644 --- a/src/hotspot/share/classfile/symbolTable.hpp +++ b/src/hotspot/share/classfile/symbolTable.hpp @@ -144,6 +144,11 @@ public: static Symbol* new_permanent_symbol(const char* name); // Rehash the string table if it gets out of balance +private: + static bool should_grow(); + +public: + static bool rehash_table_expects_safepoint_rehashing(); static void rehash_table(); static bool needs_rehashing() { return _needs_rehashing; } static inline void update_needs_rehash(bool rehash) { diff --git a/src/hotspot/share/code/icBuffer.cpp b/src/hotspot/share/code/icBuffer.cpp index f9a3d345a3f..a43d3678ad3 100644 --- a/src/hotspot/share/code/icBuffer.cpp +++ b/src/hotspot/share/code/icBuffer.cpp @@ -161,6 +161,20 @@ void InlineCacheBuffer::refill_ic_stubs() { VMThread::execute(&ibf); } +bool InlineCacheBuffer::needs_update_inline_caches() { + // Stub removal + if (buffer()->number_of_stubs() > 0) { + return true; + } + + // Release pending CompiledICHolder + if (pending_icholder_count() > 0) { + return true; + } + + return false; +} + void InlineCacheBuffer::update_inline_caches() { if (buffer()->number_of_stubs() > 0) { if (TraceICBuffer) { diff --git a/src/hotspot/share/code/icBuffer.hpp b/src/hotspot/share/code/icBuffer.hpp index 135e11928f9..d385b99d59d 100644 --- a/src/hotspot/share/code/icBuffer.hpp +++ b/src/hotspot/share/code/icBuffer.hpp @@ -167,6 +167,7 @@ class InlineCacheBuffer: public AllStatic { static bool contains(address instruction_address); // removes the ICStubs after backpatching + static bool needs_update_inline_caches(); static void update_inline_caches(); static void refill_ic_stubs(); diff --git a/src/hotspot/share/runtime/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp index 2ff593a0143..cfd1f3bbb1a 100644 --- a/src/hotspot/share/runtime/safepoint.cpp +++ b/src/hotspot/share/runtime/safepoint.cpp @@ -547,6 +547,28 @@ public: _do_lazy_roots(!VMThread::vm_operation()->skip_thread_oop_barriers() && Universe::heap()->uses_stack_watermark_barrier()) {} + uint expected_num_workers() const { + uint workers = 0; + + if (SymbolTable::rehash_table_expects_safepoint_rehashing()) { + workers++; + } + + if (StringTable::rehash_table_expects_safepoint_rehashing()) { + workers++; + } + + if (InlineCacheBuffer::needs_update_inline_caches()) { + workers++; + } + + if (_do_lazy_roots) { + workers++; + } + + return MAX2(1, workers); + } + void work(uint worker_id) { // These tasks are ordered by relative length of time to execute so that potentially longer tasks start first. if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_SYMBOL_TABLE_REHASH)) { @@ -601,9 +623,11 @@ void SafepointSynchronize::do_cleanup_tasks() { assert(heap != nullptr, "heap not initialized yet?"); ParallelCleanupTask cleanup; WorkerThreads* cleanup_workers = heap->safepoint_workers(); - if (cleanup_workers != nullptr) { + const uint expected_num_workers = cleanup.expected_num_workers(); + if (cleanup_workers != nullptr && expected_num_workers > 1) { // Parallel cleanup using GC provided thread pool. - cleanup_workers->run_task(&cleanup); + const uint num_workers = MIN2(expected_num_workers, cleanup_workers->active_workers()); + cleanup_workers->run_task(&cleanup, num_workers); } else { // Serial cleanup using VMThread. cleanup.work(0);