Skip to content

Commit 4e9483d

Browse files
committedFeb 29, 2024
Improve CompileTrainingData::_init_deps_left handling

File tree

9 files changed

+144
-21
lines changed

9 files changed

+144
-21
lines changed
 

‎src/hotspot/share/cds/cds_globals.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@
141141
\
142142
product(bool, ArchiveLoaderLookupCache, false, \
143143
"Archive app loader's positive and negative lookup cache") \
144-
144+
\
145+
product(bool, VerifyTrainingData, trueInDebug, DIAGNOSTIC, \
146+
"Verify archived training data") \
145147

146148
// end of CDS_FLAGS
147149

‎src/hotspot/share/classfile/compactHashtable.hpp

+20
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,26 @@ class CompactHashtable : public SimpleCompactHashtable {
302302
}
303303
}
304304

305+
template<typename Function>
306+
inline void iterate(Function function) const { // lambda enabled API
307+
for (u4 i = 0; i < _bucket_count; i++) {
308+
u4 bucket_info = _buckets[i];
309+
u4 bucket_offset = BUCKET_OFFSET(bucket_info);
310+
int bucket_type = BUCKET_TYPE(bucket_info);
311+
u4* entry = _entries + bucket_offset;
312+
313+
if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
314+
function(decode(entry[0]));
315+
} else {
316+
u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]);
317+
while (entry < entry_max) {
318+
function(decode(entry[1]));
319+
entry += 2;
320+
}
321+
}
322+
}
323+
}
324+
305325
void print_table_statistics(outputStream* st, const char* name) {
306326
st->print_cr("%s statistics:", name);
307327
int total_entries = 0;

‎src/hotspot/share/code/SCCache.cpp

+65
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "memory/universe.hpp"
5454
#include "oops/klass.inline.hpp"
5555
#include "oops/method.inline.hpp"
56+
#include "oops/trainingData.hpp"
5657
#include "prims/jvmtiThreadState.hpp"
5758
#include "runtime/atomic.hpp"
5859
#include "runtime/flags/flagSetting.hpp"
@@ -185,6 +186,11 @@ void SCCache::close() {
185186
SCCache::print_statistics_on(&log);
186187
log.cr();
187188
SCCache::print_timers_on(&log);
189+
190+
LogStreamHandle(Info, scc, init) log1;
191+
if (log1.is_enabled()) {
192+
SCCache::print_unused_entries_on(&log1);
193+
}
188194
}
189195
}
190196

@@ -3320,6 +3326,47 @@ void SCCache::print_on(outputStream* st) {
33203326
}
33213327
}
33223328

3329+
void SCCache::print_unused_entries_on(outputStream* st) {
3330+
LogStreamHandle(Info, scc, init) info;
3331+
if (info.is_enabled()) {
3332+
SCCache::iterate([&](SCCEntry* entry) {
3333+
if (!entry->is_loaded()) {
3334+
MethodTrainingData* mtd = MethodTrainingData::lookup_for(entry->method());
3335+
if (mtd != nullptr) {
3336+
if (mtd->has_holder()) {
3337+
if (mtd->holder()->method_holder()->is_initialized()) {
3338+
ResourceMark rm;
3339+
mtd->iterate_all_compiles([&](CompileTrainingData* ctd) {
3340+
if ((uint)ctd->level() == entry->comp_level()) {
3341+
if (ctd->init_deps_left() == 0) {
3342+
CompiledMethod* cm = mtd->holder()->code();
3343+
if (cm == nullptr) {
3344+
if (mtd->holder()->queued_for_compilation()) {
3345+
return; // scheduled for compilation
3346+
}
3347+
} else if ((uint)cm->comp_level() >= entry->comp_level()) {
3348+
return; // already online compiled and superseded by a more optimal method
3349+
}
3350+
info.print("SCC entry not loaded: ");
3351+
ctd->print_on(&info);
3352+
info.cr();
3353+
}
3354+
}
3355+
});
3356+
} else {
3357+
// not yet initialized
3358+
}
3359+
} else {
3360+
info.print("SCC entry doesn't have a holder: ");
3361+
mtd->print_on(&info);
3362+
info.cr();
3363+
}
3364+
}
3365+
}
3366+
});
3367+
}
3368+
}
3369+
33233370
void SCCReader::print_on(outputStream* st) {
33243371
uint entry_position = _entry->offset();
33253372
set_read_position(entry_position);
@@ -3967,3 +4014,21 @@ int SCAddressTable::id_for_address(address addr, RelocIterator reloc, CodeBuffer
39674014
}
39684015
return id;
39694016
}
4017+
4018+
template<typename Function>
4019+
void SCCache::iterate(Function function) { // lambda enabled API
4020+
SCCache* cache = open_for_read();
4021+
if (cache != nullptr) {
4022+
ReadingMark rdmk;
4023+
4024+
uint count = cache->_load_header->entries_count();
4025+
uint* search_entries = (uint*)cache->addr(cache->_load_header->entries_offset()); // [id, index]
4026+
SCCEntry* load_entries = (SCCEntry*)(search_entries + 2 * count);
4027+
4028+
for (uint i = 0; i < count; i++) {
4029+
int index = search_entries[2*i + 1];
4030+
SCCEntry* entry = &(load_entries[index]);
4031+
function(entry);
4032+
}
4033+
}
4034+
}

‎src/hotspot/share/code/SCCache.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -527,11 +527,15 @@ class SCCache : public CHeapObj<mtCode> {
527527
static SCCEntry* find_code_entry(const methodHandle& method, uint comp_level);
528528
static void preload_code(JavaThread* thread);
529529

530+
template<typename Function>
531+
static void iterate(Function function); // lambda enabled API
532+
530533
static void add_C_string(const char* str);
531534

532535
static void print_on(outputStream* st);
533536
static void print_statistics_on(outputStream* st);
534537
static void print_timers_on(outputStream* st);
538+
static void print_unused_entries_on(outputStream* st);
535539

536540
static void new_workflow_start_writing_cache() NOT_CDS_JAVA_HEAP_RETURN;
537541
static void new_workflow_end_writing_cache() NOT_CDS_JAVA_HEAP_RETURN;

‎src/hotspot/share/compiler/compilationPolicy.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ void CompilationPolicy::replay_training_at_init(InstanceKlass* klass, TRAPS) {
268268
} else {
269269
replay_training_at_init_impl(klass, THREAD);
270270
}
271+
guarantee(!HAS_PENDING_EXCEPTION, "");
271272
}
272273
}
273274

‎src/hotspot/share/oops/instanceKlass.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ void InstanceKlass::initialize_from_cds(TRAPS) {
844844
log_class_init(THREAD, this);
845845
set_init_thread(THREAD);
846846
set_initialization_state_and_notify(fully_initialized, CHECK);
847+
CompilationPolicy::replay_training_at_init(this, THREAD);
847848
return;
848849
}
849850

‎src/hotspot/share/oops/trainingData.cpp

+34-9
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,6 @@ void TrainingData::initialize() {
101101
TrainingDataLocker::initialize();
102102
}
103103
if (have_data()) {
104-
// Initialize dependency tracking
105-
training_data_set()->iterate_all([](const Key* k, TrainingData* td) {
106-
if (td->is_MethodTrainingData()) {
107-
td->as_MethodTrainingData()->initialize_deps_tracking();
108-
}
109-
});
110-
111104
if (_recompilation_schedule != nullptr && _recompilation_schedule->length() > 0) {
112105
const int size = _recompilation_schedule->length();
113106
_recompilation_status = NEW_C_HEAP_ARRAY(bool, size, mtCompiler);
@@ -118,6 +111,17 @@ void TrainingData::initialize() {
118111
}
119112
}
120113

114+
void TrainingData::verify() {
115+
if (TrainingData::have_data()) {
116+
archived_training_data_dictionary()->iterate([&](TrainingData* td) {
117+
if (td->is_MethodTrainingData()) {
118+
td->as_MethodTrainingData()->verify();
119+
}
120+
});
121+
}
122+
}
123+
124+
121125
TrainingData::Key::Key(const KlassTrainingData* klass, Symbol* method_name, Symbol* signature)
122126
: Key(method_name, signature, klass) {}
123127

@@ -278,7 +282,27 @@ void CompileTrainingData::dec_init_deps_left(KlassTrainingData* ktd) {
278282
assert(_init_deps.contains(ktd), "");
279283
assert(_init_deps_left > 0, "");
280284

281-
Atomic::sub(&_init_deps_left, 1);
285+
uint init_deps_left1 = Atomic::sub(&_init_deps_left, 1);
286+
287+
if (log.is_enabled()) {
288+
uint init_deps_left2 = compute_init_deps_left();
289+
log.print("init_deps_left: %d (%d)", init_deps_left1, init_deps_left2);
290+
ktd->print_on(&log, true);
291+
}
292+
}
293+
294+
uint CompileTrainingData::compute_init_deps_left(bool count_initialized) {
295+
int left = 0;
296+
for (int i = 0; i < _init_deps.length(); i++) {
297+
KlassTrainingData* ktd = _init_deps.at(i);
298+
// Ignore symbolic refs and already initialized classes (unless explicitly requested).
299+
if (ktd->has_holder()) {
300+
if (!ktd->holder()->is_initialized() || count_initialized) {
301+
++left;
302+
}
303+
}
304+
}
305+
return left;
282306
}
283307

284308
void CompileTrainingData::print_on(outputStream* st, bool name_only) const {
@@ -1037,18 +1061,19 @@ void MethodTrainingData::restore_unshareable_info(TRAPS) {
10371061
if (_final_profile != nullptr) {
10381062
_final_profile->restore_unshareable_info(CHECK);
10391063
}
1040-
initialize_deps_tracking();
10411064
}
10421065

10431066
void CompileTrainingData::remove_unshareable_info() {
10441067
TrainingData::remove_unshareable_info();
10451068
_init_deps.remove_unshareable_info();
10461069
_ci_records.remove_unshareable_info();
1070+
_init_deps_left = compute_init_deps_left(true);
10471071
}
10481072

10491073
void CompileTrainingData::restore_unshareable_info(TRAPS) {
10501074
TrainingData::restore_unshareable_info(CHECK);
10511075
_init_deps.restore_unshareable_info(CHECK);
10521076
_ci_records.restore_unshareable_info(CHECK);
1077+
guarantee(_init_deps_left == (int)compute_init_deps_left(), "mismatch");
10531078
}
10541079
#endif // INCLUDE_CDS

‎src/hotspot/share/oops/trainingData.hpp

+12-11
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ class TrainingData : public Metadata {
265265

266266
static void initialize();
267267

268+
static void verify();
269+
268270
// Widget for recording dependencies, as an N-to-M graph relation,
269271
// possibly cyclic.
270272
template<typename E>
@@ -630,16 +632,10 @@ class CompileTrainingData : public TrainingData {
630632
}
631633
void dec_init_deps_left(KlassTrainingData* ktd);
632634
int init_deps_left() const {
633-
return _init_deps_left;
634-
}
635-
void initialize_deps_tracking() {
636-
for (int i = 0; i < _init_deps.length(); i++) {
637-
KlassTrainingData* dep = _init_deps.at(i);
638-
if (dep->has_holder() && !dep->holder()->is_initialized()) {
639-
_init_deps_left++; // ignore symbolic refs && already initialized classes
640-
}
641-
}
635+
return Atomic::load(&_init_deps_left);
642636
}
637+
uint compute_init_deps_left(bool count_initialized = false);
638+
643639
void record_compilation_queued(CompileTask* task);
644640
void record_compilation_start(CompileTask* task);
645641
void record_compilation_end(CompileTask* task);
@@ -785,8 +781,13 @@ class MethodTrainingData : public TrainingData {
785781
}
786782
}
787783

788-
void initialize_deps_tracking() {
789-
iterate_all_compiles([](CompileTrainingData* ctd) { ctd->initialize_deps_tracking(); });
784+
void verify() {
785+
iterate_all_compiles([](CompileTrainingData* ctd) {
786+
int init_deps_left1 = ctd->init_deps_left();
787+
int init_deps_left2 = ctd->compute_init_deps_left();
788+
guarantee(init_deps_left1 == init_deps_left2, "mismatch: %d %d %d",
789+
init_deps_left1, init_deps_left2, ctd->init_deps_left());
790+
});
790791
}
791792

792793
virtual void metaspace_pointers_do(MetaspaceClosure* iter);

‎src/hotspot/share/runtime/java.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,10 @@ void before_exit(JavaThread* thread, bool halt) {
591591
// Note: we don't wait until it actually dies.
592592
os::terminate_signal_thread();
593593

594+
if (VerifyTrainingData) {
595+
TrainingData::verify();
596+
}
597+
594598
print_statistics();
595599
Universe::heap()->print_tracing_info();
596600

0 commit comments

Comments
 (0)
Please sign in to comment.