8325871: Move StringTable and SymbolTable rehashing calls
Reviewed-by: eosterlund, aboldtch
This commit is contained in:
parent
9e98118f28
commit
7734466c46
@ -55,6 +55,7 @@
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "runtime/timerTrace.hpp"
|
||||
#include "runtime/trimNativeHeap.hpp"
|
||||
#include "runtime/vmOperations.hpp"
|
||||
#include "services/diagnosticCommand.hpp"
|
||||
#include "utilities/concurrentHashTable.inline.hpp"
|
||||
#include "utilities/concurrentHashTableTasks.inline.hpp"
|
||||
@ -267,10 +268,17 @@ size_t StringTable::table_size() {
|
||||
return ((size_t)1) << _local_table->get_size_log2(Thread::current());
|
||||
}
|
||||
|
||||
bool StringTable::has_work() {
|
||||
return Atomic::load_acquire(&_has_work);
|
||||
}
|
||||
|
||||
void StringTable::trigger_concurrent_work() {
|
||||
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
Atomic::store(&_has_work, true);
|
||||
Service_lock->notify_all();
|
||||
// Avoid churn on ServiceThread
|
||||
if (!has_work()) {
|
||||
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
Atomic::store(&_has_work, true);
|
||||
Service_lock->notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
// Probing
|
||||
@ -308,6 +316,13 @@ class StringTableGet : public StackObj {
|
||||
}
|
||||
};
|
||||
|
||||
void StringTable::update_needs_rehash(bool rehash) {
|
||||
if (rehash) {
|
||||
_needs_rehashing = true;
|
||||
trigger_concurrent_work();
|
||||
}
|
||||
}
|
||||
|
||||
oop StringTable::do_lookup(const jchar* name, int len, uintx hash) {
|
||||
Thread* thread = Thread::current();
|
||||
StringTableLookupJchar lookup(thread, hash, name, len);
|
||||
@ -499,15 +514,20 @@ void StringTable::gc_notification(size_t num_dead) {
|
||||
}
|
||||
}
|
||||
|
||||
bool StringTable::has_work() {
|
||||
return Atomic::load_acquire(&_has_work);
|
||||
bool StringTable::should_grow() {
|
||||
return get_load_factor() > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached();
|
||||
}
|
||||
|
||||
void StringTable::do_concurrent_work(JavaThread* jt) {
|
||||
double load_factor = get_load_factor();
|
||||
log_debug(stringtable, perf)("Concurrent work, live factor: %g", load_factor);
|
||||
// Rehash if needed. Rehashing goes to a safepoint but the rest of this
|
||||
// work is concurrent.
|
||||
if (needs_rehashing() && maybe_rehash_table()) {
|
||||
Atomic::release_store(&_has_work, false);
|
||||
return; // done, else grow
|
||||
}
|
||||
log_debug(stringtable, perf)("Concurrent work, live factor: %g", get_load_factor());
|
||||
// We prefer growing, since that also removes dead items
|
||||
if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {
|
||||
if (should_grow()) {
|
||||
grow(jt);
|
||||
} else {
|
||||
clean_dead_entries(jt);
|
||||
@ -515,85 +535,48 @@ void StringTable::do_concurrent_work(JavaThread* jt) {
|
||||
Atomic::release_store(&_has_work, false);
|
||||
}
|
||||
|
||||
// Rehash
|
||||
bool StringTable::do_rehash() {
|
||||
if (!_local_table->is_safepoint_safe()) {
|
||||
return false;
|
||||
}
|
||||
// Called at VM_Operation safepoint
|
||||
void StringTable::rehash_table() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be called at safepoint");
|
||||
// The ServiceThread initiates the rehashing so it is not resizing.
|
||||
assert (_local_table->is_safepoint_safe(), "Should not be resizing now");
|
||||
|
||||
_alt_hash_seed = AltHashing::compute_seed();
|
||||
|
||||
// We use current size, not max size.
|
||||
size_t new_size = _local_table->get_size_log2(Thread::current());
|
||||
StringTableHash* new_table = new StringTableHash(new_size, END_SIZE, REHASH_LEN, true);
|
||||
// Use alt hash from now on
|
||||
_alt_hash = true;
|
||||
if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) {
|
||||
_alt_hash = false;
|
||||
delete new_table;
|
||||
return false;
|
||||
}
|
||||
_local_table->rehash_nodes_to(Thread::current(), new_table);
|
||||
|
||||
// free old table
|
||||
delete _local_table;
|
||||
_local_table = new_table;
|
||||
|
||||
return true;
|
||||
_rehashed = true;
|
||||
_needs_rehashing = false;
|
||||
}
|
||||
|
||||
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() {
|
||||
bool StringTable::maybe_rehash_table() {
|
||||
log_debug(stringtable)("Table imbalanced, rehashing called.");
|
||||
|
||||
// Grow instead of rehash.
|
||||
if (should_grow()) {
|
||||
log_debug(stringtable)("Choosing growing over rehashing.");
|
||||
trigger_concurrent_work();
|
||||
_needs_rehashing = false;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// Already rehashed.
|
||||
if (_rehashed) {
|
||||
log_warning(stringtable)("Rehashing already done, still long lists.");
|
||||
trigger_concurrent_work();
|
||||
_needs_rehashing = false;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
_alt_hash_seed = AltHashing::compute_seed();
|
||||
{
|
||||
if (do_rehash()) {
|
||||
_rehashed = true;
|
||||
} else {
|
||||
log_info(stringtable)("Resizes in progress rehashing skipped.");
|
||||
}
|
||||
}
|
||||
_needs_rehashing = false;
|
||||
VM_RehashStringTable op;
|
||||
VMThread::execute(&op);
|
||||
return true; // return true because we tried.
|
||||
}
|
||||
|
||||
// Statistics
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -71,8 +71,6 @@ class StringTable : AllStatic {
|
||||
|
||||
static void print_table_statistics(outputStream* st);
|
||||
|
||||
static bool do_rehash();
|
||||
|
||||
public:
|
||||
static size_t table_size();
|
||||
static TableStatistics get_table_statistics();
|
||||
@ -94,16 +92,11 @@ class StringTable : AllStatic {
|
||||
// Rehash the string table if it gets out of balance
|
||||
private:
|
||||
static bool should_grow();
|
||||
|
||||
static bool maybe_rehash_table();
|
||||
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) {
|
||||
if (rehash) {
|
||||
_needs_rehashing = true;
|
||||
}
|
||||
}
|
||||
static inline void update_needs_rehash(bool rehash);
|
||||
|
||||
// Sharing
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -246,10 +246,15 @@ size_t SymbolTable::table_size() {
|
||||
return ((size_t)1) << _local_table->get_size_log2(Thread::current());
|
||||
}
|
||||
|
||||
bool SymbolTable::has_work() { return Atomic::load_acquire(&_has_work); }
|
||||
|
||||
void SymbolTable::trigger_cleanup() {
|
||||
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
_has_work = true;
|
||||
Service_lock->notify_all();
|
||||
// Avoid churn on ServiceThread
|
||||
if (!has_work()) {
|
||||
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
_has_work = true;
|
||||
Service_lock->notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
class SymbolsDo : StackObj {
|
||||
@ -413,6 +418,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void SymbolTable::update_needs_rehash(bool rehash) {
|
||||
if (rehash) {
|
||||
_needs_rehashing = true;
|
||||
trigger_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) {
|
||||
Thread* thread = Thread::current();
|
||||
SymbolTableLookup lookup(name, len, hash);
|
||||
@ -772,7 +784,7 @@ void SymbolTable::clean_dead_entries(JavaThread* jt) {
|
||||
}
|
||||
|
||||
void SymbolTable::check_concurrent_work() {
|
||||
if (_has_work) {
|
||||
if (has_work()) {
|
||||
return;
|
||||
}
|
||||
// We should clean/resize if we have
|
||||
@ -785,98 +797,70 @@ void SymbolTable::check_concurrent_work() {
|
||||
}
|
||||
}
|
||||
|
||||
bool SymbolTable::should_grow() {
|
||||
return get_load_factor() > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached();
|
||||
}
|
||||
|
||||
void SymbolTable::do_concurrent_work(JavaThread* jt) {
|
||||
double load_factor = get_load_factor();
|
||||
log_debug(symboltable, perf)("Concurrent work, live factor: %g", load_factor);
|
||||
// Rehash if needed. Rehashing goes to a safepoint but the rest of this
|
||||
// work is concurrent.
|
||||
if (needs_rehashing() && maybe_rehash_table()) {
|
||||
Atomic::release_store(&_has_work, false);
|
||||
return; // done, else grow
|
||||
}
|
||||
log_debug(symboltable, perf)("Concurrent work, live factor: %g", get_load_factor());
|
||||
// We prefer growing, since that also removes dead items
|
||||
if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {
|
||||
if (should_grow()) {
|
||||
grow(jt);
|
||||
} else {
|
||||
clean_dead_entries(jt);
|
||||
}
|
||||
_has_work = false;
|
||||
Atomic::release_store(&_has_work, false);
|
||||
}
|
||||
|
||||
// Rehash
|
||||
bool SymbolTable::do_rehash() {
|
||||
if (!_local_table->is_safepoint_safe()) {
|
||||
return false;
|
||||
}
|
||||
// Called at VM_Operation safepoint
|
||||
void SymbolTable::rehash_table() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be called at safepoint");
|
||||
// The ServiceThread initiates the rehashing so it is not resizing.
|
||||
assert (_local_table->is_safepoint_safe(), "Should not be resizing now");
|
||||
|
||||
_alt_hash_seed = AltHashing::compute_seed();
|
||||
|
||||
// We use current size
|
||||
size_t new_size = _local_table->get_size_log2(Thread::current());
|
||||
SymbolTableHash* new_table = new SymbolTableHash(new_size, END_SIZE, REHASH_LEN, true);
|
||||
// Use alt hash from now on
|
||||
_alt_hash = true;
|
||||
if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) {
|
||||
_alt_hash = false;
|
||||
delete new_table;
|
||||
return false;
|
||||
}
|
||||
_local_table->rehash_nodes_to(Thread::current(), new_table);
|
||||
|
||||
// free old table
|
||||
delete _local_table;
|
||||
_local_table = new_table;
|
||||
|
||||
return true;
|
||||
_rehashed = true;
|
||||
_needs_rehashing = false;
|
||||
}
|
||||
|
||||
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() {
|
||||
bool SymbolTable::maybe_rehash_table() {
|
||||
log_debug(symboltable)("Table imbalanced, rehashing called.");
|
||||
|
||||
// Grow instead of rehash.
|
||||
if (should_grow()) {
|
||||
log_debug(symboltable)("Choosing growing over rehashing.");
|
||||
trigger_cleanup();
|
||||
_needs_rehashing = false;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Already rehashed.
|
||||
if (_rehashed) {
|
||||
log_warning(symboltable)("Rehashing already done, still long lists.");
|
||||
trigger_cleanup();
|
||||
_needs_rehashing = false;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
_alt_hash_seed = AltHashing::compute_seed();
|
||||
|
||||
if (do_rehash()) {
|
||||
_rehashed = true;
|
||||
} else {
|
||||
log_info(symboltable)("Resizes in progress rehashing skipped.");
|
||||
}
|
||||
|
||||
_needs_rehashing = false;
|
||||
VM_RehashSymbolTable op;
|
||||
VMThread::execute(&op);
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -98,7 +98,6 @@ class SymbolTable : public AllStatic {
|
||||
static void print_table_statistics(outputStream* st);
|
||||
|
||||
static void try_rehash_table();
|
||||
static bool do_rehash();
|
||||
|
||||
public:
|
||||
// The symbol table
|
||||
@ -114,7 +113,7 @@ public:
|
||||
static void create_table();
|
||||
|
||||
static void do_concurrent_work(JavaThread* jt);
|
||||
static bool has_work() { return _has_work; }
|
||||
static bool has_work();
|
||||
static void trigger_cleanup();
|
||||
|
||||
// Probing
|
||||
@ -146,16 +145,12 @@ public:
|
||||
// Rehash the string table if it gets out of balance
|
||||
private:
|
||||
static bool should_grow();
|
||||
static bool maybe_rehash_table();
|
||||
|
||||
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) {
|
||||
if (rehash) {
|
||||
_needs_rehashing = true;
|
||||
}
|
||||
}
|
||||
static inline void update_needs_rehash(bool rehash);
|
||||
|
||||
// Heap dumper and CDS
|
||||
static void symbols_do(SymbolClosure *cl);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,9 +23,6 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "code/nmethod.hpp"
|
||||
#include "code/pcDesc.hpp"
|
||||
@ -510,13 +507,6 @@ void SafepointSynchronize::end() {
|
||||
post_safepoint_end_event(event, safepoint_id());
|
||||
}
|
||||
|
||||
bool SafepointSynchronize::is_cleanup_needed() {
|
||||
// Need a safepoint if some inline cache buffers is non-empty
|
||||
if (StringTable::needs_rehashing()) return true;
|
||||
if (SymbolTable::needs_rehashing()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
class ParallelCleanupTask : public WorkerTask {
|
||||
private:
|
||||
SubTasksDone _subtasks;
|
||||
@ -548,14 +538,6 @@ public:
|
||||
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 (_do_lazy_roots) {
|
||||
workers++;
|
||||
}
|
||||
@ -564,21 +546,6 @@ public:
|
||||
}
|
||||
|
||||
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)) {
|
||||
if (SymbolTable::needs_rehashing()) {
|
||||
Tracer t("rehashing symbol table");
|
||||
SymbolTable::rehash_table();
|
||||
}
|
||||
}
|
||||
|
||||
if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_STRING_TABLE_REHASH)) {
|
||||
if (StringTable::needs_rehashing()) {
|
||||
Tracer t("rehashing string table");
|
||||
StringTable::rehash_table();
|
||||
}
|
||||
}
|
||||
|
||||
if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_LAZY_ROOT_PROCESSING)) {
|
||||
if (_do_lazy_roots) {
|
||||
Tracer t("lazy partial thread root processing");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -71,8 +71,6 @@ class SafepointSynchronize : AllStatic {
|
||||
// The enums are listed in the order of the tasks when done serially.
|
||||
enum SafepointCleanupTasks {
|
||||
SAFEPOINT_CLEANUP_LAZY_ROOT_PROCESSING,
|
||||
SAFEPOINT_CLEANUP_SYMBOL_TABLE_REHASH,
|
||||
SAFEPOINT_CLEANUP_STRING_TABLE_REHASH,
|
||||
SAFEPOINT_CLEANUP_REQUEST_OOPSTORAGE_CLEANUP,
|
||||
// Leave this one last.
|
||||
SAFEPOINT_CLEANUP_NUM_TASKS
|
||||
@ -158,7 +156,6 @@ public:
|
||||
// Exception handling for page polling
|
||||
static void handle_polling_page_exception(JavaThread *thread);
|
||||
|
||||
static bool is_cleanup_needed();
|
||||
static void do_cleanup_tasks();
|
||||
|
||||
static void set_is_at_safepoint() { _state = _synchronized; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,7 +37,6 @@
|
||||
#define VM_OPS_DO(template) \
|
||||
template(Halt) \
|
||||
template(SafepointALot) \
|
||||
template(Cleanup) \
|
||||
template(ThreadDump) \
|
||||
template(PrintThreads) \
|
||||
template(FindDeadlocks) \
|
||||
@ -106,6 +105,8 @@
|
||||
template(ClassLoaderHierarchyOperation) \
|
||||
template(DumpHashtable) \
|
||||
template(CleanClassLoaderDataMetaspaces) \
|
||||
template(RehashStringTable) \
|
||||
template(RehashSymbolTable) \
|
||||
template(PrintCompileQueue) \
|
||||
template(PrintClassHierarchy) \
|
||||
template(PrintClasses) \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,6 +24,8 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
@ -103,6 +105,14 @@ void VM_CleanClassLoaderDataMetaspaces::doit() {
|
||||
ClassLoaderDataGraph::walk_metadata_and_clean_metaspaces();
|
||||
}
|
||||
|
||||
void VM_RehashStringTable::doit() {
|
||||
StringTable::rehash_table();
|
||||
}
|
||||
|
||||
void VM_RehashSymbolTable::doit() {
|
||||
SymbolTable::rehash_table();
|
||||
}
|
||||
|
||||
VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason) {
|
||||
_thread = thread;
|
||||
_id = id;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,11 +54,6 @@ class VM_SafepointALot: public VM_EmptyOperation {
|
||||
VMOp_Type type() const { return VMOp_SafepointALot; }
|
||||
};
|
||||
|
||||
class VM_Cleanup: public VM_EmptyOperation {
|
||||
public:
|
||||
VMOp_Type type() const { return VMOp_Cleanup; }
|
||||
};
|
||||
|
||||
// empty vm op, evaluated just to force a safepoint
|
||||
class VM_ForceSafepoint: public VM_EmptyOperation {
|
||||
public:
|
||||
@ -98,6 +93,20 @@ class VM_CleanClassLoaderDataMetaspaces : public VM_Operation {
|
||||
void doit();
|
||||
};
|
||||
|
||||
class VM_RehashStringTable : public VM_Operation {
|
||||
public:
|
||||
VM_RehashStringTable() {}
|
||||
VMOp_Type type() const { return VMOp_RehashStringTable; }
|
||||
void doit();
|
||||
};
|
||||
|
||||
class VM_RehashSymbolTable : public VM_Operation {
|
||||
public:
|
||||
VM_RehashSymbolTable() {}
|
||||
VMOp_Type type() const { return VMOp_RehashSymbolTable; }
|
||||
void doit();
|
||||
};
|
||||
|
||||
// Deopt helper that can deoptimize frames in threads other than the
|
||||
// current thread. Only used through Deoptimization::deoptimize_frame.
|
||||
class VM_DeoptimizeFrame: public VM_Operation {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -98,14 +98,14 @@ void VMOperationTimeoutTask::disarm() {
|
||||
// Implementation of VMThread stuff
|
||||
|
||||
static VM_SafepointALot safepointALot_op;
|
||||
static VM_Cleanup cleanup_op;
|
||||
static VM_ForceSafepoint no_op;
|
||||
|
||||
bool VMThread::_should_terminate = false;
|
||||
bool VMThread::_terminated = false;
|
||||
Monitor* VMThread::_terminate_lock = nullptr;
|
||||
VMThread* VMThread::_vm_thread = nullptr;
|
||||
VM_Operation* VMThread::_cur_vm_operation = nullptr;
|
||||
VM_Operation* VMThread::_next_vm_operation = &cleanup_op; // Prevent any thread from setting an operation until VM thread is ready.
|
||||
VM_Operation* VMThread::_next_vm_operation = &no_op; // Prevent any thread from setting an operation until VM thread is ready.
|
||||
PerfCounter* VMThread::_perf_accumulated_vm_operation_time = nullptr;
|
||||
VMOperationTimeoutTask* VMThread::_timeout_task = nullptr;
|
||||
|
||||
@ -337,9 +337,7 @@ void VMThread::setup_periodic_safepoint_if_needed() {
|
||||
if (!max_time_exceeded) {
|
||||
return;
|
||||
}
|
||||
if (SafepointSynchronize::is_cleanup_needed()) {
|
||||
_next_vm_operation = &cleanup_op;
|
||||
} else if (SafepointALot) {
|
||||
if (SafepointALot) {
|
||||
_next_vm_operation = &safepointALot_op;
|
||||
}
|
||||
}
|
||||
@ -499,7 +497,7 @@ void VMThread::loop() {
|
||||
|
||||
// Need to set a calling thread for ops not passed
|
||||
// via the normal way.
|
||||
cleanup_op.set_calling_thread(_vm_thread);
|
||||
no_op.set_calling_thread(_vm_thread);
|
||||
safepointALot_op.set_calling_thread(_vm_thread);
|
||||
|
||||
while (true) {
|
||||
|
@ -524,8 +524,9 @@ class ConcurrentHashTable : public CHeapObj<F> {
|
||||
void statistics_to(Thread* thread, VALUE_SIZE_FUNC& vs_f, outputStream* st,
|
||||
const char* table_name);
|
||||
|
||||
// Moves all nodes from this table to to_cht
|
||||
bool try_move_nodes_to(Thread* thread, ConcurrentHashTable<CONFIG, F>* to_cht);
|
||||
// Moves all nodes from this table to to_cht with new hash code.
|
||||
// Must be done at a safepoint.
|
||||
void rehash_nodes_to(Thread* thread, ConcurrentHashTable<CONFIG, F>* to_cht);
|
||||
|
||||
// Scoped multi getter.
|
||||
class MultiGetHandle : private ScopedCS {
|
||||
|
@ -1288,12 +1288,10 @@ inline void ConcurrentHashTable<CONFIG, F>::
|
||||
}
|
||||
|
||||
template <typename CONFIG, MEMFLAGS F>
|
||||
inline bool ConcurrentHashTable<CONFIG, F>::
|
||||
try_move_nodes_to(Thread* thread, ConcurrentHashTable<CONFIG, F>* to_cht)
|
||||
inline void ConcurrentHashTable<CONFIG, F>::
|
||||
rehash_nodes_to(Thread* thread, ConcurrentHashTable<CONFIG, F>* to_cht)
|
||||
{
|
||||
if (!try_resize_lock(thread)) {
|
||||
return false;
|
||||
}
|
||||
assert(is_safepoint_safe(), "rehashing is at a safepoint - cannot be resizing");
|
||||
assert(_new_table == nullptr || _new_table == POISON_PTR, "Must be null");
|
||||
for (size_t bucket_it = 0; bucket_it < _table->_size; bucket_it++) {
|
||||
Bucket* bucket = _table->get_bucket(bucket_it);
|
||||
@ -1313,8 +1311,6 @@ inline bool ConcurrentHashTable<CONFIG, F>::
|
||||
}
|
||||
}
|
||||
}
|
||||
unlock_resize_lock(thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // SHARE_UTILITIES_CONCURRENTHASHTABLE_INLINE_HPP
|
||||
|
@ -399,7 +399,8 @@ static void cht_move_to(Thread* thr) {
|
||||
EXPECT_TRUE(from_cht->insert(thr, stl3, val3)) << "Insert unique value failed.";
|
||||
|
||||
SimpleTestTable* to_cht = new SimpleTestTable();
|
||||
EXPECT_TRUE(from_cht->try_move_nodes_to(thr, to_cht)) << "Moving nodes to new table failed";
|
||||
// This is single threaded and not shared
|
||||
from_cht->rehash_nodes_to(thr, to_cht);
|
||||
|
||||
ChtCountScan scan_old;
|
||||
EXPECT_TRUE(from_cht->try_scan(thr, scan_old)) << "Scanning table should work.";
|
||||
|
Loading…
Reference in New Issue
Block a user