Skip to content

Commit 3daa03c

Browse files
iklamshipilev
andcommitted
8358680: AOT cache creation fails: no strings should have been added
Co-authored-by: Aleksey Shipilev <shade@openjdk.org> Reviewed-by: coleenp, shade
1 parent 24117c6 commit 3daa03c

File tree

8 files changed

+63
-18
lines changed

8 files changed

+63
-18
lines changed

src/hotspot/share/classfile/stringTable.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "classfile/javaClasses.inline.hpp"
3333
#include "classfile/stringTable.hpp"
3434
#include "classfile/vmClasses.hpp"
35+
#include "compiler/compileBroker.hpp"
3536
#include "gc/shared/collectedHeap.hpp"
3637
#include "gc/shared/oopStorage.inline.hpp"
3738
#include "gc/shared/oopStorageSet.hpp"
@@ -115,6 +116,7 @@ OopStorage* StringTable::_oop_storage;
115116

116117
static size_t _current_size = 0;
117118
static volatile size_t _items_count = 0;
119+
DEBUG_ONLY(static bool _disable_interning_during_cds_dump = false);
118120

119121
volatile bool _alt_hash = false;
120122

@@ -346,6 +348,10 @@ bool StringTable::has_work() {
346348
return Atomic::load_acquire(&_has_work);
347349
}
348350

351+
size_t StringTable::items_count_acquire() {
352+
return Atomic::load_acquire(&_items_count);
353+
}
354+
349355
void StringTable::trigger_concurrent_work() {
350356
// Avoid churn on ServiceThread
351357
if (!has_work()) {
@@ -504,6 +510,9 @@ oop StringTable::intern(const char* utf8_string, TRAPS) {
504510
}
505511

506512
oop StringTable::intern(const StringWrapper& name, TRAPS) {
513+
assert(!Atomic::load_acquire(&_disable_interning_during_cds_dump),
514+
"All threads that may intern strings should have been stopped before CDS starts copying the interned string table");
515+
507516
// shared table always uses java_lang_String::hash_code
508517
unsigned int hash = hash_wrapped_string(name);
509518
oop found_string = lookup_shared(name, hash);
@@ -793,7 +802,7 @@ void StringTable::verify() {
793802
}
794803

795804
// Verification and comp
796-
class VerifyCompStrings : StackObj {
805+
class StringTable::VerifyCompStrings : StackObj {
797806
static unsigned string_hash(oop const& str) {
798807
return java_lang_String::hash_code_noupdate(str);
799808
}
@@ -805,7 +814,7 @@ class VerifyCompStrings : StackObj {
805814
string_hash, string_equals> _table;
806815
public:
807816
size_t _errors;
808-
VerifyCompStrings() : _table(unsigned(_items_count / 8) + 1, 0 /* do not resize */), _errors(0) {}
817+
VerifyCompStrings() : _table(unsigned(items_count_acquire() / 8) + 1, 0 /* do not resize */), _errors(0) {}
809818
bool operator()(WeakHandle* val) {
810819
oop s = val->resolve();
811820
if (s == nullptr) {
@@ -939,20 +948,31 @@ oop StringTable::lookup_shared(const jchar* name, int len) {
939948
return _shared_table.lookup(wrapped_name, java_lang_String::hash_code(name, len), 0);
940949
}
941950

942-
// This is called BEFORE we enter the CDS safepoint. We can allocate heap objects.
943-
// This should be called when we know no more strings will be added (which will be easy
944-
// to guarantee because CDS runs with a single Java thread. See JDK-8253495.)
951+
// This is called BEFORE we enter the CDS safepoint. We can still allocate Java object arrays to
952+
// be used by the shared strings table.
945953
void StringTable::allocate_shared_strings_array(TRAPS) {
946954
if (!CDSConfig::is_dumping_heap()) {
947955
return;
948956
}
949-
assert(CDSConfig::allow_only_single_java_thread(), "No more interned strings can be added");
950957

951-
if (_items_count > (size_t)max_jint) {
952-
fatal("Too many strings to be archived: %zu", _items_count);
958+
CompileBroker::wait_for_no_active_tasks();
959+
960+
precond(CDSConfig::allow_only_single_java_thread());
961+
962+
// At this point, no more strings will be added:
963+
// - There's only a single Java thread (this thread). It no longer executes Java bytecodes
964+
// so JIT compilation will eventually stop.
965+
// - CompileBroker has no more active tasks, so all JIT requests have been processed.
966+
967+
// This flag will be cleared after intern table dumping has completed, so we can run the
968+
// compiler again (for future AOT method compilation, etc).
969+
DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, true));
970+
971+
if (items_count_acquire() > (size_t)max_jint) {
972+
fatal("Too many strings to be archived: %zu", items_count_acquire());
953973
}
954974

955-
int total = (int)_items_count;
975+
int total = (int)items_count_acquire();
956976
size_t single_array_size = objArrayOopDesc::object_size(total);
957977

958978
log_info(aot)("allocated string table for %d strings", total);
@@ -972,7 +992,7 @@ void StringTable::allocate_shared_strings_array(TRAPS) {
972992
// This can only happen if you have an extremely large number of classes that
973993
// refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern
974994
// but bail out for safety.
975-
log_error(aot)("Too many strings to be archived: %zu", _items_count);
995+
log_error(aot)("Too many strings to be archived: %zu", items_count_acquire());
976996
MetaspaceShared::unrecoverable_writing_error();
977997
}
978998

@@ -1070,7 +1090,7 @@ oop StringTable::init_shared_strings_array() {
10701090

10711091
void StringTable::write_shared_table() {
10721092
_shared_table.reset();
1073-
CompactHashtableWriter writer((int)_items_count, ArchiveBuilder::string_stats());
1093+
CompactHashtableWriter writer((int)items_count_acquire(), ArchiveBuilder::string_stats());
10741094

10751095
int index = 0;
10761096
auto copy_into_shared_table = [&] (WeakHandle* val) {
@@ -1084,6 +1104,8 @@ void StringTable::write_shared_table() {
10841104
};
10851105
_local_table->do_safepoint_scan(copy_into_shared_table);
10861106
writer.dump(&_shared_table, "string");
1107+
1108+
DEBUG_ONLY(Atomic::release_store(&_disable_interning_during_cds_dump, false));
10871109
}
10881110

10891111
void StringTable::set_shared_strings_array_index(int root_index) {

src/hotspot/share/classfile/stringTable.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class StringTableConfig;
4040

4141
class StringTable : AllStatic {
4242
friend class StringTableConfig;
43-
43+
class VerifyCompStrings;
4444
static volatile bool _has_work;
4545

4646
// Set if one bucket is out of balance due to hash algorithm deficiency
@@ -74,6 +74,7 @@ class StringTable : AllStatic {
7474

7575
static void item_added();
7676
static void item_removed();
77+
static size_t items_count_acquire();
7778

7879
static oop intern(const StringWrapper& name, TRAPS);
7980
static oop do_intern(const StringWrapper& name, uintx hash, TRAPS);

src/hotspot/share/compiler/compileBroker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,10 @@ void CompileBroker::wait_for_completion(CompileTask* task) {
17501750
}
17511751
}
17521752

1753+
void CompileBroker::wait_for_no_active_tasks() {
1754+
CompileTask::wait_for_no_active_tasks();
1755+
}
1756+
17531757
/**
17541758
* Initialize compiler thread(s) + compiler object(s). The postcondition
17551759
* of this function is that the compiler runtimes are initialized and that

src/hotspot/share/compiler/compileBroker.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,9 @@ class CompileBroker: AllStatic {
383383
static bool is_compilation_disabled_forever() {
384384
return _should_compile_new_jobs == shutdown_compilation;
385385
}
386+
387+
static void wait_for_no_active_tasks();
388+
386389
static void handle_full_code_cache(CodeBlobType code_blob_type);
387390
// Ensures that warning is only printed once.
388391
static bool should_print_compiler_warning() {

src/hotspot/share/compiler/compileTask.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@
3737
#include "runtime/mutexLocker.hpp"
3838

3939
CompileTask* CompileTask::_task_free_list = nullptr;
40+
int CompileTask::_active_tasks = 0;
4041

4142
/**
4243
* Allocate a CompileTask, from the free list if possible.
4344
*/
4445
CompileTask* CompileTask::allocate() {
45-
MutexLocker locker(CompileTaskAlloc_lock);
46+
MonitorLocker locker(CompileTaskAlloc_lock);
4647
CompileTask* task = nullptr;
4748

4849
if (_task_free_list != nullptr) {
@@ -56,14 +57,15 @@ CompileTask* CompileTask::allocate() {
5657
}
5758
assert(task->is_free(), "Task must be free.");
5859
task->set_is_free(false);
60+
_active_tasks++;
5961
return task;
6062
}
6163

6264
/**
6365
* Add a task to the free list.
6466
*/
6567
void CompileTask::free(CompileTask* task) {
66-
MutexLocker locker(CompileTaskAlloc_lock);
68+
MonitorLocker locker(CompileTaskAlloc_lock);
6769
if (!task->is_free()) {
6870
if ((task->_method_holder != nullptr && JNIHandles::is_weak_global_handle(task->_method_holder))) {
6971
JNIHandles::destroy_weak_global(task->_method_holder);
@@ -79,6 +81,17 @@ void CompileTask::free(CompileTask* task) {
7981
task->set_is_free(true);
8082
task->set_next(_task_free_list);
8183
_task_free_list = task;
84+
_active_tasks--;
85+
if (_active_tasks == 0) {
86+
locker.notify_all();
87+
}
88+
}
89+
}
90+
91+
void CompileTask::wait_for_no_active_tasks() {
92+
MonitorLocker locker(CompileTaskAlloc_lock);
93+
while (_active_tasks > 0) {
94+
locker.wait();
8295
}
8396
}
8497

src/hotspot/share/compiler/compileTask.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,7 @@ class CompileTask : public CHeapObj<mtCompiler> {
8383

8484
private:
8585
static CompileTask* _task_free_list;
86+
static int _active_tasks;
8687
int _compile_id;
8788
Method* _method;
8889
jobject _method_holder;
@@ -123,6 +124,7 @@ class CompileTask : public CHeapObj<mtCompiler> {
123124

124125
static CompileTask* allocate();
125126
static void free(CompileTask* task);
127+
static void wait_for_no_active_tasks();
126128

127129
int compile_id() const { return _compile_id; }
128130
Method* method() const { return _method; }

src/hotspot/share/runtime/mutexLocker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Monitor* CompileTaskWait_lock = nullptr;
8484
Monitor* MethodCompileQueue_lock = nullptr;
8585
Monitor* CompileThread_lock = nullptr;
8686
Monitor* Compilation_lock = nullptr;
87-
Mutex* CompileTaskAlloc_lock = nullptr;
87+
Monitor* CompileTaskAlloc_lock = nullptr;
8888
Mutex* CompileStatistics_lock = nullptr;
8989
Mutex* DirectivesStack_lock = nullptr;
9090
Monitor* Terminator_lock = nullptr;
@@ -346,7 +346,7 @@ void mutex_init() {
346346
MUTEX_DEFL(G1RareEvent_lock , PaddedMutex , Threads_lock, true);
347347
}
348348

349-
MUTEX_DEFL(CompileTaskAlloc_lock , PaddedMutex , MethodCompileQueue_lock);
349+
MUTEX_DEFL(CompileTaskAlloc_lock , PaddedMonitor, MethodCompileQueue_lock);
350350
MUTEX_DEFL(CompileTaskWait_lock , PaddedMonitor, MethodCompileQueue_lock);
351351

352352
#if INCLUDE_PARALLELGC

src/hotspot/share/runtime/mutexLocker.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ extern Monitor* CompileThread_lock; // a lock held by compile threa
8686
extern Monitor* Compilation_lock; // a lock used to pause compilation
8787
extern Mutex* TrainingData_lock; // a lock used when accessing training records
8888
extern Monitor* TrainingReplayQueue_lock; // a lock held when class are added/removed to the training replay queue
89-
extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
89+
extern Monitor* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
9090
extern Monitor* CompileTaskWait_lock; // a lock held when CompileTasks are waited/notified
9191
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
9292
extern Mutex* DirectivesStack_lock; // a lock held when mutating the dirstack and ref counting directives

0 commit comments

Comments
 (0)