< prev index next > src/hotspot/share/classfile/stringTable.cpp
Print this page
#include "classfile/altHashing.hpp"
#include "classfile/compactHashtable.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/vmClasses.hpp"
+ #include "compiler/compileBroker.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/oopStorage.inline.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "gc/shared/stringdedup/stringDedup.hpp"
#include "logging/log.hpp"
volatile bool StringTable::_needs_rehashing = false;
OopStorage* StringTable::_oop_storage;
static size_t _current_size = 0;
static volatile size_t _items_count = 0;
+ DEBUG_ONLY(static bool _disable_interning_during_cds_dump = false);
volatile bool _alt_hash = false;
static bool _rehashed = false;
static uint64_t _alt_hash_seed = 0;
bool StringTable::has_work() {
return Atomic::load_acquire(&_has_work);
}
+ size_t StringTable::items_count_acquire() {
+ return Atomic::load_acquire(&_items_count);
+ }
+
void StringTable::trigger_concurrent_work() {
// Avoid churn on ServiceThread
if (!has_work()) {
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
Atomic::store(&_has_work, true);
oop result = intern(name, CHECK_NULL);
return result;
}
oop StringTable::intern(const StringWrapper& name, TRAPS) {
+ assert(!Atomic::load_acquire(&_disable_interning_during_cds_dump),
+ "All threads that may intern strings should have been stopped before CDS starts copying the interned string table");
+
// shared table always uses java_lang_String::hash_code
unsigned int hash = hash_wrapped_string(name);
oop found_string = lookup_shared(name, hash);
if (found_string != nullptr) {
return found_string;
VerifyStrings vs;
_local_table->do_safepoint_scan(vs);
}
// Verification and comp
- class VerifyCompStrings : StackObj {
+ class StringTable::VerifyCompStrings : StackObj {
static unsigned string_hash(oop const& str) {
return java_lang_String::hash_code_noupdate(str);
}
static bool string_equals(oop const& a, oop const& b) {
return java_lang_String::equals(a, b);
ResizeableResourceHashtable<oop, bool, AnyObj::C_HEAP, mtInternal,
string_hash, string_equals> _table;
public:
size_t _errors;
- VerifyCompStrings() : _table(unsigned(_items_count / 8) + 1, 0 /* do not resize */), _errors(0) {}
+ VerifyCompStrings() : _table(unsigned(items_count_acquire() / 8) + 1, 0 /* do not resize */), _errors(0) {}
bool operator()(WeakHandle* val) {
oop s = val->resolve();
if (s == nullptr) {
return true;
}
StringWrapper wrapped_name(name, len);
// len is required but is already part of StringWrapper, so 0 is used
return _shared_table.lookup(wrapped_name, java_lang_String::hash_code(name, len), 0);
}
- // This is called BEFORE we enter the CDS safepoint. We can allocate heap objects.
- // This should be called when we know no more strings will be added (which will be easy
- // to guarantee because CDS runs with a single Java thread. See JDK-8253495.)
+ // This is called BEFORE we enter the CDS safepoint. We can still allocate Java object arrays to
+ // be used by the shared strings table.
void StringTable::allocate_shared_strings_array(TRAPS) {
if (!CDSConfig::is_dumping_heap()) {
return;
}
- assert(CDSConfig::allow_only_single_java_thread(), "No more interned strings can be added");
- if (_items_count > (size_t)max_jint) {
- fatal("Too many strings to be archived: %zu", _items_count);
+ CompileBroker::wait_for_no_active_tasks();
+
+ precond(CDSConfig::allow_only_single_java_thread());
+
+ // At this point, no more strings will be added:
+ // - There's only a single Java thread (this thread). It no longer executes Java bytecodes
+ // so JIT compilation will eventually stop.
+ // - CompileBroker has no more active tasks, so all JIT requests have been processed.
+
+ // This flag will be cleared after intern table dumping has completed, so we can run the
+ // compiler again (for future AOT method compilation, etc).
+ DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, true));
+
+ if (items_count_acquire() > (size_t)max_jint) {
+ fatal("Too many strings to be archived: %zu", items_count_acquire());
}
- int total = (int)_items_count;
+ int total = (int)items_count_acquire();
size_t single_array_size = objArrayOopDesc::object_size(total);
log_info(aot)("allocated string table for %d strings", total);
if (!ArchiveHeapWriter::is_too_large_to_archive(single_array_size)) {
if (ArchiveHeapWriter::is_too_large_to_archive(secondary_array_size)) {
// This can only happen if you have an extremely large number of classes that
// refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern
// but bail out for safety.
- log_error(aot)("Too many strings to be archived: %zu", _items_count);
+ log_error(aot)("Too many strings to be archived: %zu", items_count_acquire());
MetaspaceShared::unrecoverable_writing_error();
}
objArrayOop primary = oopFactory::new_objArray(vmClasses::Object_klass(), primary_array_length, CHECK);
objArrayHandle primaryHandle(THREAD, primary);
return array;
};
void StringTable::write_shared_table() {
_shared_table.reset();
- CompactHashtableWriter writer((int)_items_count, ArchiveBuilder::string_stats());
+ CompactHashtableWriter writer((int)items_count_acquire(), ArchiveBuilder::string_stats());
int index = 0;
auto copy_into_shared_table = [&] (WeakHandle* val) {
oop string = val->peek();
if (string != nullptr && !ArchiveHeapWriter::is_string_too_large_to_archive(string)) {
}
return true;
};
_local_table->do_safepoint_scan(copy_into_shared_table);
writer.dump(&_shared_table, "string");
+
+ DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, false));
}
void StringTable::set_shared_strings_array_index(int root_index) {
_shared_strings_array_root_index = root_index;
}
void StringTable::serialize_shared_table_header(SerializeClosure* soc) {
+ if (soc->writing() && !CDSConfig::is_dumping_heap()) {
+ _shared_table.reset();
+ _is_two_dimensional_shared_strings_array = false;
+ _shared_strings_array_root_index = -1;
+ }
+
_shared_table.serialize_header(soc);
if (soc->writing()) {
// Sanity. Make sure we don't use the shared table at dump time
_shared_table.reset();
< prev index next >