diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index 0c947655752..203ec3a3ec4 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -310,7 +310,9 @@ static void set_serialized(const T* ptr) { assert(ptr != nullptr, "invariant"); if (current_epoch()) { CLEAR_THIS_EPOCH_CLEARED_BIT(ptr); + assert(!IS_THIS_EPOCH_CLEARED_BIT_SET(ptr), "invariant"); } + assert(IS_PREVIOUS_EPOCH_CLEARED_BIT_SET(ptr), "invariant"); SET_SERIALIZED(ptr); assert(IS_SERIALIZED(ptr), "invariant"); } @@ -929,9 +931,11 @@ void set_serialized(MethodPtr method) { assert(method != nullptr, "invariant"); if (current_epoch()) { CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(method); + assert(!IS_THIS_EPOCH_METHOD_CLEARED_BIT_SET(method), "invariant"); } assert(unloading() ? true : METHOD_IS_NOT_SERIALIZED(method), "invariant"); SET_METHOD_SERIALIZED(method); + assert(IS_PREVIOUS_EPOCH_METHOD_CLEARED_BIT_SET(method), "invariant"); assert(METHOD_IS_SERIALIZED(method), "invariant"); } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp index 237745b13d9..bfff7eaaf1b 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp @@ -96,6 +96,8 @@ class ClearArtifact { assert(IS_NOT_TRANSIENT(value), "invariant"); SET_PREVIOUS_EPOCH_CLEARED_BIT(value); CLEAR_PREVIOUS_EPOCH_METHOD_AND_CLASS(value); + assert(IS_THIS_EPOCH_CLEARED_BIT_SET(value), "invariant"); + assert(IS_PREVIOUS_EPOCH_CLEARED_BIT_SET(value), "invariant"); return true; } }; @@ -111,6 +113,8 @@ class ClearArtifact { assert(METHOD_IS_NOT_TRANSIENT(method), "invariant"); SET_PREVIOUS_EPOCH_METHOD_CLEARED_BIT(method); CLEAR_PREVIOUS_EPOCH_METHOD_FLAG(method); + assert(IS_THIS_EPOCH_METHOD_CLEARED_BIT_SET(method), "invariant"); + assert(IS_PREVIOUS_EPOCH_METHOD_CLEARED_BIT_SET(method), "invariant"); return true; } }; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp index f07078eaf06..d2973f74872 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, 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 @@ -50,22 +50,22 @@ static traceid atomic_inc(traceid volatile* const dest, traceid stride = 1) { static traceid next_class_id() { static volatile traceid class_id_counter = LAST_TYPE_ID + 1; // + 1 is for the void.class primitive - return atomic_inc(&class_id_counter) << TRACE_ID_SHIFT; + return (atomic_inc(&class_id_counter) << TRACE_ID_SHIFT) | EPOCH_CLEARED_BITS; } static traceid next_module_id() { static volatile traceid module_id_counter = 0; - return atomic_inc(&module_id_counter) << TRACE_ID_SHIFT; + return (atomic_inc(&module_id_counter) << TRACE_ID_SHIFT) | EPOCH_CLEARED_BITS; } static traceid next_package_id() { static volatile traceid package_id_counter = 0; - return atomic_inc(&package_id_counter) << TRACE_ID_SHIFT; + return (atomic_inc(&package_id_counter) << TRACE_ID_SHIFT) | EPOCH_CLEARED_BITS; } static traceid next_class_loader_data_id() { static volatile traceid cld_id_counter = 0; - return atomic_inc(&cld_id_counter) << TRACE_ID_SHIFT; + return (atomic_inc(&cld_id_counter) << TRACE_ID_SHIFT) | EPOCH_CLEARED_BITS; } static bool found_jdk_internal_event_klass = false; @@ -201,18 +201,18 @@ traceid JfrTraceId::load_raw(jclass jc) { // used by CDS / APPCDS as part of "remove_unshareable_info" void JfrTraceId::remove(const Klass* k) { assert(k != nullptr, "invariant"); - // Mask off and store the event flags. + // Mask off and store the event flags and epoch clear bits. // This mechanism will retain the event specific flags // in the archive, allowing for event flag restoration // when renewing the traceid on klass revival. - k->set_trace_id(EVENT_KLASS_MASK(k)); + k->set_trace_id(EPOCH_CLEARED_BITS | EVENT_KLASS_MASK(k)); } // used by CDS / APPCDS as part of "remove_unshareable_info" void JfrTraceId::remove(const Method* method) { assert(method != nullptr, "invariant"); - // Clear all bits. - method->set_trace_flags(0); + // Clear tag bits and set epoch cleared bits. + method->set_trace_flags(static_cast(EPOCH_CLEARED_BITS)); } // used by CDS / APPCDS as part of "restore_unshareable_info" diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp index ed302335274..5f986121ea0 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp @@ -157,9 +157,9 @@ inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass) { inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) { assert(klass != nullptr, "invariant"); - assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant"); assert(method != nullptr, "invariant"); assert(klass == method->method_holder(), "invariant"); + assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant"); if (should_tag(method)) { // the method is already logically tagged, just like the klass, // but because of redefinition, the latest Method* @@ -174,9 +174,9 @@ inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Metho inline traceid JfrTraceIdLoadBarrier::load_leakp_previuos_epoch(const Klass* klass, const Method* method) { assert(klass != nullptr, "invariant"); - assert(METHOD_AND_CLASS_USED_PREVIOUS_EPOCH(klass), "invariant"); assert(method != nullptr, "invariant"); assert(klass == method->method_holder(), "invariant"); + assert(METHOD_AND_CLASS_USED_PREVIOUS_EPOCH(klass), "invariant"); if (METHOD_FLAG_NOT_USED_PREVIOUS_EPOCH(method)) { // the method is already logically tagged, just like the klass, // but because of redefinition, the latest Method* diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp index 3736c070f0a..f53eecad2cf 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -48,6 +48,7 @@ #define EPOCH_0_CLEARED_BIT (EPOCH_0_CLEARED_META_BIT << META_SHIFT) #define EPOCH_1_CLEARED_META_BIT (BIT << 1) #define EPOCH_1_CLEARED_BIT (EPOCH_1_CLEARED_META_BIT << META_SHIFT) +#define EPOCH_CLEARED_BITS (EPOCH_1_CLEARED_BIT | EPOCH_0_CLEARED_BIT) #define LEAKP_META_BIT (BIT << 2) #define LEAKP_BIT (LEAKP_META_BIT << META_SHIFT) #define TRANSIENT_META_BIT (BIT << 3) @@ -136,6 +137,8 @@ #define IS_TRANSIENT(ptr) (TRACE_ID_PREDICATE(ptr, TRANSIENT_BIT)) #define IS_NOT_TRANSIENT(ptr) (!(IS_TRANSIENT(ptr))) #define SET_SERIALIZED(ptr) (TRACE_ID_META_TAG(ptr, SERIALIZED_META_BIT)) +#define IS_THIS_EPOCH_CLEARED_BIT_SET(ptr) (TRACE_ID_PREDICATE(ptr, (THIS_EPOCH_BIT << META_SHIFT))) +#define IS_PREVIOUS_EPOCH_CLEARED_BIT_SET(ptr) (TRACE_ID_PREDICATE(ptr, (PREVIOUS_EPOCH_BIT << META_SHIFT))) #define IS_SERIALIZED(ptr) (TRACE_ID_PREDICATE(ptr, SERIALIZED_BIT)) #define IS_NOT_SERIALIZED(ptr) (!(IS_SERIALIZED(ptr))) #define SHOULD_TAG(ptr) (NOT_USED_THIS_EPOCH(ptr)) @@ -161,5 +164,7 @@ #define CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(ptr) (METHOD_META_MASK_CLEAR(ptr,(~(THIS_EPOCH_BIT)))) #define IS_THIS_EPOCH_METHOD_CLEARED(ptr) (METHOD_FLAG_PREDICATE(method, THIS_EPOCH_BIT)) #define IS_PREVIOUS_EPOCH_METHOD_CLEARED(ptr) (METHOD_FLAG_PREDICATE(method, PREVIOUS_EPOCH_BIT)) +#define IS_THIS_EPOCH_METHOD_CLEARED_BIT_SET(ptr) (METHOD_FLAG_PREDICATE(ptr, (THIS_EPOCH_BIT << META_SHIFT))) +#define IS_PREVIOUS_EPOCH_METHOD_CLEARED_BIT_SET(ptr) (METHOD_FLAG_PREDICATE(ptr, (PREVIOUS_EPOCH_BIT << META_SHIFT))) #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDMACROS_HPP diff --git a/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp b/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp index 353e5c3f07c..c73ece42645 100644 --- a/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp +++ b/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp @@ -44,11 +44,13 @@ #define REMOVE_METHOD_ID(method) JfrTraceId::remove(method); #define RESTORE_ID(k) JfrTraceId::restore(k); +static constexpr const uint16_t cleared_epoch_bits = 512 | 256; + class JfrTraceFlag { private: mutable uint16_t _flags; public: - JfrTraceFlag() : _flags(0) {} + JfrTraceFlag() : _flags(cleared_epoch_bits) {} bool is_set(uint16_t flag) const { return (_flags & flag) != 0; } @@ -96,9 +98,8 @@ class JfrTraceFlag { uint8_t* trace_meta_addr() const { \ return _trace_flags.meta_addr(); \ } \ - void copy_trace_flags(uint8_t src_flags) const { \ - uint8_t flags = *_trace_flags.flags_addr(); \ - _trace_flags.set_flags(flags | src_flags); \ + void copy_trace_flags(uint16_t rhs_flags) const { \ + _trace_flags.set_flags(_trace_flags.flags() | rhs_flags); \ } #endif // SHARE_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 84010493dbc..344ef7802a2 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -1174,7 +1174,7 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( } } } - JFR_ONLY(k_new_method->copy_trace_flags(*k_old_method->trace_flags_addr());) + JFR_ONLY(k_new_method->copy_trace_flags(k_old_method->trace_flags());) log_trace(redefine, class, normalize) ("Method matched: new: %s [%d] == old: %s [%d]", k_new_method->name_and_sig_as_C_string(), ni, k_old_method->name_and_sig_as_C_string(), oi);