8357671: JFR: Remove JfrTraceIdEpoch synchronizing

Reviewed-by: egahlin
This commit is contained in:
Markus Grönlund 2025-06-04 08:19:24 +00:00
parent edf92721c2
commit 955bfcd550
7 changed files with 23 additions and 51 deletions

View File

@ -497,15 +497,10 @@ typedef CompositeOperation<MutexedWriteOperation, ReleaseOperation> WriteRelease
typedef VirtualThreadLocalCheckpointWriteOp<JfrCheckpointManager::Buffer> VirtualThreadLocalCheckpointOperation;
typedef MutexedWriteOp<VirtualThreadLocalCheckpointOperation> VirtualThreadLocalWriteOperation;
void JfrCheckpointManager::begin_epoch_shift() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
JfrTraceIdEpoch::begin_epoch_shift();
}
void JfrCheckpointManager::end_epoch_shift() {
void JfrCheckpointManager::shift_epoch() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
DEBUG_ONLY(const u1 current_epoch = JfrTraceIdEpoch::current();)
JfrTraceIdEpoch::end_epoch_shift();
JfrTraceIdEpoch::shift_epoch();
assert(current_epoch != JfrTraceIdEpoch::current(), "invariant");
JfrStringPool::on_epoch_shift();
}

View File

@ -96,8 +96,7 @@ class JfrCheckpointManager : public JfrCHeapObj {
void clear_type_set();
void write_type_set();
void begin_epoch_shift();
void end_epoch_shift();
void shift_epoch();
static void on_unloading_classes();
void on_rotation();

View File

@ -31,7 +31,7 @@
/*
* The epoch generation is the range [1-32767].
*
* When the epoch value is stored in a thread object,
* When the epoch value is stored in a vthread object,
* the most significant bit of the u2 is used to denote
* thread exclusion, i.e 1 << 15 == 32768 denotes exclusion.
*/
@ -39,32 +39,17 @@ u2 JfrTraceIdEpoch::_generation = 0;
JfrSignal JfrTraceIdEpoch::_tag_state;
bool JfrTraceIdEpoch::_method_tracer_state = false;
bool JfrTraceIdEpoch::_epoch_state = false;
bool JfrTraceIdEpoch::_synchronizing = false;
static constexpr const u2 epoch_generation_overflow = excluded_bit;
void JfrTraceIdEpoch::begin_epoch_shift() {
void JfrTraceIdEpoch::shift_epoch() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
_synchronizing = true;
OrderAccess::fence();
}
void JfrTraceIdEpoch::end_epoch_shift() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
assert(_synchronizing, "invariant");
_epoch_state = !_epoch_state;
++_generation;
if (epoch_generation_overflow == _generation) {
if (++_generation == epoch_generation_overflow) {
_generation = 1;
}
assert(_generation != 0, "invariant");
assert(_generation < epoch_generation_overflow, "invariant");
OrderAccess::storestore();
_synchronizing = false;
}
bool JfrTraceIdEpoch::is_synchronizing() {
return Atomic::load_acquire(&_synchronizing);
}
void JfrTraceIdEpoch::set_method_tracer_tag_state() {

View File

@ -26,7 +26,6 @@
#define SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDEPOCH_HPP
#include "jfr/utilities/jfrSignal.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "memory/allStatic.hpp"
#define BIT 1
@ -41,16 +40,17 @@
#define EPOCH_0_METHOD_AND_CLASS_BITS (METHOD_AND_CLASS_BITS << EPOCH_0_SHIFT)
#define EPOCH_1_METHOD_AND_CLASS_BITS (METHOD_AND_CLASS_BITS << EPOCH_1_SHIFT)
// Epoch alternation on each rotation allow for concurrent tagging.
// The epoch shift happens only during a safepoint.
//
// _synchronizing is a transition state, the purpose of which is to
// have JavaThreads that run _thread_in_native (i.e. Compiler threads)
// respect the current epoch shift in-progress during the safepoint.
//
// _changed_tag_state == true signals an incremental modification to artifact tagging
// (klasses, methods, CLDs, etc), purpose of which is to trigger collection of artifacts.
//
/*
* An epoch shift or alternation on each rotation enables concurrent tagging.
* The epoch shift happens only during a safepoint.
*
* _generation - mainly used with virtual threads, but also for the generational string pool in Java.
* _tag_state - signals an incremental modification to artifact tagging (klasses, methods, CLDs, etc)
* purpose of which is to trigger a collection of artifacts.
* _method_tracer_state - a special notification state only used with method timing and tracing.
* _epoch_state - the fundamental binary epoch state that shifts on each rotation during a safepoint.
*/
class JfrTraceIdEpoch : AllStatic {
friend class JfrCheckpointManager;
private:
@ -58,10 +58,8 @@ class JfrTraceIdEpoch : AllStatic {
static JfrSignal _tag_state;
static bool _method_tracer_state;
static bool _epoch_state;
static bool _synchronizing;
static void begin_epoch_shift();
static void end_epoch_shift();
static void shift_epoch();
public:
static bool epoch() {

View File

@ -484,13 +484,12 @@ void JfrRecorderService::invoke_safepoint_clear() {
void JfrRecorderService::safepoint_clear() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
_checkpoint_manager.begin_epoch_shift();
_storage.clear();
_checkpoint_manager.notify_threads();
_chunkwriter.set_time_stamp();
JfrDeprecationManager::on_safepoint_clear();
JfrStackTraceRepository::clear();
_checkpoint_manager.end_epoch_shift();
_checkpoint_manager.shift_epoch();
}
void JfrRecorderService::post_safepoint_clear() {
@ -593,14 +592,13 @@ void JfrRecorderService::invoke_safepoint_write() {
void JfrRecorderService::safepoint_write() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
_checkpoint_manager.begin_epoch_shift();
JfrStackTraceRepository::clear_leak_profiler();
_checkpoint_manager.on_rotation();
_storage.write_at_safepoint();
_chunkwriter.set_time_stamp();
JfrDeprecationManager::on_safepoint_write();
write_stacktrace(_stack_trace_repository, _chunkwriter, true);
_checkpoint_manager.end_epoch_shift();
_checkpoint_manager.shift_epoch();
}
void JfrRecorderService::post_safepoint_write() {

View File

@ -44,8 +44,6 @@
static int generation_offset = invalid_offset;
static jobject string_pool = nullptr;
static unsigned short generation = 0;
static bool setup_string_pool_offsets(TRAPS) {
const char class_name[] = "jdk/jfr/internal/StringPool";
Symbol* const k_sym = SymbolTable::new_symbol(class_name);
@ -281,9 +279,8 @@ void JfrStringPool::register_full(BufferPtr buffer, Thread* thread) {
void JfrStringPool::on_epoch_shift() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
assert(!JfrTraceIdEpoch::is_synchronizing(), "invariant");
assert(string_pool != nullptr, "invariant");
oop mirror = JfrJavaSupport::resolve_non_null(string_pool);
assert(mirror != nullptr, "invariant");
mirror->short_field_put(generation_offset, generation++);
mirror->short_field_put(generation_offset, JfrTraceIdEpoch::epoch_generation());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2025, 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
@ -51,7 +51,7 @@ public final class StringPool {
private static int preCacheOld = 0;
/* max size bytes */
private static long currentSizeUTF16;
/* string pool generation (0-65535) set by the JVM on epoch shift. Not private to avoid being optimized away. */
/* The string pool epoch generation is the range [1-32767] set by the JVM on epoch shift. Not private to avoid being optimized away. */
static short generation = 0;
/* internalSid is a composite id [48-bit externalSid][16-bit generation]. */