From 6fc9d856c9e6418f7d82267b092c425cdcd1480d Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Tue, 23 Sep 2025 18:14:02 -0700 Subject: [PATCH 1/2] Need a lock around _ci_records access. Respect snapshot flag. --- src/hotspot/share/oops/trainingData.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/oops/trainingData.hpp b/src/hotspot/share/oops/trainingData.hpp index 9c645d437dc13..79961ebb6b9b2 100644 --- a/src/hotspot/share/oops/trainingData.hpp +++ b/src/hotspot/share/oops/trainingData.hpp @@ -591,6 +591,7 @@ class CompileTrainingData : public TrainingData { DepList _data; public: OptionalReturnType find(const Args&... args) { + TrainingDataLocker l; ArgumentsType a(args...); for (int i = 0; i < _data.length(); i++) { if (_data.at(i).arguments() == a) { @@ -599,8 +600,11 @@ class CompileTrainingData : public TrainingData { } return OptionalReturnType(false, ReturnType()); } - bool append_if_missing(const ReturnType& result, const Args&... args) { - return _data.append_if_missing(Record(result, ArgumentsType(args...))); + void append_if_missing(const ReturnType& result, const Args&... args) { + TrainingDataLocker l; + if (l.can_add()) { + _data.append_if_missing(Record(result, ArgumentsType(args...))); + } } #if INCLUDE_CDS void remove_unshareable_info() { _data.remove_unshareable_info(); } From bb3add97f94789843be108ed11897f005506ca9b Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Wed, 24 Sep 2025 10:48:51 -0700 Subject: [PATCH 2/2] Make DepList more defensive against non-MT-safe use --- src/hotspot/share/oops/trainingData.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/hotspot/share/oops/trainingData.hpp b/src/hotspot/share/oops/trainingData.hpp index 79961ebb6b9b2..d214a03a2844d 100644 --- a/src/hotspot/share/oops/trainingData.hpp +++ b/src/hotspot/share/oops/trainingData.hpp @@ -152,6 +152,9 @@ class TrainingData : public Metadata { _lock_mode = need_data() ? +1 : -1; // if -1, we go lock-free #endif } + static void assert_locked_or_snapshotted() { + assert(safely_locked() || _snapshot, "use under TrainingDataLocker or after snapshot"); + } static void assert_locked() { assert(safely_locked(), "use under TrainingDataLocker"); } @@ -338,20 +341,24 @@ class TrainingData : public Metadata { } int length() const { + TrainingDataLocker::assert_locked_or_snapshotted(); return (_deps_dyn != nullptr ? _deps_dyn->length() : _deps != nullptr ? _deps->length() : 0); } E* adr_at(int i) const { + TrainingDataLocker::assert_locked_or_snapshotted(); return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i) : _deps != nullptr ? _deps->adr_at(i) : nullptr); } E at(int i) const { + TrainingDataLocker::assert_locked_or_snapshotted(); assert(i >= 0 && i < length(), "oob"); return *adr_at(i); } bool append_if_missing(E dep) { + TrainingDataLocker::assert_can_add(); if (_deps_dyn == nullptr) { _deps_dyn = new GrowableArrayCHeap(10); _deps_dyn->append(dep); @@ -361,23 +368,27 @@ class TrainingData : public Metadata { } } bool remove_if_existing(E dep) { + TrainingDataLocker::assert_can_add(); if (_deps_dyn != nullptr) { return _deps_dyn->remove_if_existing(dep); } return false; } void clear() { + TrainingDataLocker::assert_can_add(); if (_deps_dyn != nullptr) { _deps_dyn->clear(); } } void append(E dep) { + TrainingDataLocker::assert_can_add(); if (_deps_dyn == nullptr) { _deps_dyn = new GrowableArrayCHeap(10); } _deps_dyn->append(dep); } bool contains(E dep) { + TrainingDataLocker::assert_locked(); for (int i = 0; i < length(); i++) { if (dep == at(i)) { return true; // found