mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-08 17:38:38 +00:00
8334781: JFR crash: assert(((((JfrTraceIdBits::load(klass)) & ((JfrTraceIdEpoch::this_epoch_method_and_class_bits()))) != 0))) failed: invariant
Reviewed-by: egahlin
This commit is contained in:
parent
d41d2a7a82
commit
67979eb077
@ -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<Method>(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");
|
||||
}
|
||||
|
||||
|
||||
@ -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<const Method*> {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
@ -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<uint16_t>(EPOCH_CLEARED_BITS));
|
||||
}
|
||||
|
||||
// used by CDS / APPCDS as part of "restore_unshareable_info"
|
||||
|
||||
@ -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*
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user