mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-05 05:30:45 +00:00
8356587: Missing object ID X in pool jdk.types.Method
Reviewed-by: egahlin Backport-of: a34994476e8f4783c9f5a83a9c3db63ad605b323
This commit is contained in:
parent
3db8262445
commit
9fe2aa59ff
@ -132,14 +132,14 @@ InstanceKlass* JfrClassTransformer::create_new_instance_klass(InstanceKlass* ik,
|
||||
}
|
||||
|
||||
// Redefining / retransforming?
|
||||
const Klass* JfrClassTransformer::find_existing_klass(const InstanceKlass* ik, JavaThread* thread) {
|
||||
const InstanceKlass* JfrClassTransformer::find_existing_klass(const InstanceKlass* ik, JavaThread* thread) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(thread != nullptr, "invariant");
|
||||
JvmtiThreadState* const state = thread->jvmti_thread_state();
|
||||
return state != nullptr ? klass_being_redefined(ik, state) : nullptr;
|
||||
}
|
||||
|
||||
const Klass* JfrClassTransformer::klass_being_redefined(const InstanceKlass* ik, JvmtiThreadState* state) {
|
||||
const InstanceKlass* JfrClassTransformer::klass_being_redefined(const InstanceKlass* ik, JvmtiThreadState* state) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(state != nullptr, "invariant");
|
||||
const GrowableArray<Klass*>* const redef_klasses = state->get_classes_being_redefined();
|
||||
@ -149,9 +149,10 @@ const Klass* JfrClassTransformer::klass_being_redefined(const InstanceKlass* ik,
|
||||
for (int i = 0; i < redef_klasses->length(); ++i) {
|
||||
const Klass* const existing_klass = redef_klasses->at(i);
|
||||
assert(existing_klass != nullptr, "invariant");
|
||||
assert(existing_klass->is_instance_klass(), "invariant");
|
||||
if (ik->name() == existing_klass->name() && ik->class_loader_data() == existing_klass->class_loader_data()) {
|
||||
// 'ik' is a scratch klass. Return the klass being redefined.
|
||||
return existing_klass;
|
||||
return InstanceKlass::cast(existing_klass);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
@ -38,10 +38,10 @@ class InstanceKlass;
|
||||
class JfrClassTransformer : AllStatic {
|
||||
private:
|
||||
static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStream* stream, TRAPS);
|
||||
static const Klass* klass_being_redefined(const InstanceKlass* ik, JvmtiThreadState* state);
|
||||
static const InstanceKlass* klass_being_redefined(const InstanceKlass* ik, JvmtiThreadState* state);
|
||||
|
||||
public:
|
||||
static const Klass* find_existing_klass(const InstanceKlass* ik, JavaThread* thread);
|
||||
static const InstanceKlass* find_existing_klass(const InstanceKlass* ik, JavaThread* thread);
|
||||
static InstanceKlass* create_instance_klass(InstanceKlass*& ik, ClassFileStream* stream, bool is_initial_load, JavaThread* thread);
|
||||
static void copy_traceid(const InstanceKlass* ik, const InstanceKlass* new_ik);
|
||||
static void transfer_cached_class_file_data(InstanceKlass* ik, InstanceKlass* new_ik, const ClassFileParser& parser, JavaThread* thread);
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include "jfr/support/jfrResolution.hpp"
|
||||
#include "jfr/support/jfrThreadLocal.hpp"
|
||||
#include "jfr/support/methodtracer/jfrMethodTracer.hpp"
|
||||
#include "jfr/support/methodtracer/jfrTraceTagging.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/instanceKlass.inline.hpp"
|
||||
#include "oops/klass.hpp"
|
||||
@ -88,12 +89,10 @@ void Jfr::on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS)
|
||||
}
|
||||
}
|
||||
|
||||
void Jfr::on_klass_redefinition(const InstanceKlass* ik, Thread* thread) {
|
||||
assert(JfrMethodTracer::in_use(), "invariant");
|
||||
JfrMethodTracer::on_klass_redefinition(ik, thread);
|
||||
void Jfr::on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass) {
|
||||
JfrTraceTagging::on_klass_redefinition(ik, scratch_klass);
|
||||
}
|
||||
|
||||
|
||||
bool Jfr::is_excluded(Thread* t) {
|
||||
return JfrJavaSupport::is_excluded(t);
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ class Jfr : AllStatic {
|
||||
static void include_thread(Thread* thread);
|
||||
static void exclude_thread(Thread* thread);
|
||||
static void on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS);
|
||||
static void on_klass_redefinition(const InstanceKlass* ik, Thread* thread);
|
||||
static void on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass);
|
||||
static void on_thread_start(Thread* thread);
|
||||
static void on_thread_exit(Thread* thread);
|
||||
static void on_resolution(const CallInfo& info, TRAPS);
|
||||
|
||||
@ -533,8 +533,9 @@ static void clear_method_tracer_klasses() {
|
||||
static void do_unloading_klass(Klass* klass) {
|
||||
assert(klass != nullptr, "invariant");
|
||||
assert(_subsystem_callback != nullptr, "invariant");
|
||||
if (klass->is_instance_klass() && InstanceKlass::cast(klass)->is_scratch_class()) {
|
||||
return;
|
||||
if (!used(klass) && klass->is_instance_klass() && InstanceKlass::cast(klass)->is_scratch_class()) {
|
||||
SET_TRANSIENT(klass);
|
||||
assert(used(klass), "invariant");
|
||||
}
|
||||
if (JfrKlassUnloading::on_unload(klass)) {
|
||||
if (JfrTraceId::has_sticky_bit(klass)) {
|
||||
|
||||
@ -152,7 +152,7 @@ public:
|
||||
if (!klass->is_instance_klass()) {
|
||||
return false;
|
||||
}
|
||||
return _current_epoch ? METHOD_USED_THIS_EPOCH(klass) : METHOD_USED_PREVIOUS_EPOCH(klass);
|
||||
return _current_epoch ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "memory/allStatic.hpp"
|
||||
|
||||
class ClassLoaderData;
|
||||
class InstanceKlass;
|
||||
class Klass;
|
||||
class Method;
|
||||
class ModuleEntry;
|
||||
@ -86,7 +87,6 @@ class JfrTraceId : public AllStatic {
|
||||
|
||||
// through load barrier
|
||||
static traceid load(const Klass* klass);
|
||||
static traceid load_previous_epoch(const Klass* klass);
|
||||
static traceid load(jclass jc, bool raw = false);
|
||||
static traceid load(const Method* method);
|
||||
static traceid load(const Klass* klass, const Method* method);
|
||||
@ -146,10 +146,8 @@ class JfrTraceId : public AllStatic {
|
||||
static void set_sticky_bit(const Method* method);
|
||||
static void clear_sticky_bit(const Klass* k);
|
||||
static void clear_sticky_bit(const Method* method);
|
||||
static bool has_timing_bit(const Klass* k);
|
||||
static void set_timing_bit(const Klass* k);
|
||||
static void clear_timing_bit(const Klass* k);
|
||||
|
||||
static bool has_timing_bit(const InstanceKlass* scratch_klass);
|
||||
static void set_timing_bit(const InstanceKlass* scratch_klass);
|
||||
};
|
||||
|
||||
#endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_HPP
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
|
||||
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp"
|
||||
#include "jfr/support/jfrKlassExtension.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/klass.hpp"
|
||||
#include "runtime/javaThread.inline.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
@ -81,10 +82,6 @@ inline traceid JfrTraceId::load_leakp_previous_epoch(const Klass* klass, const M
|
||||
return JfrTraceIdLoadBarrier::load_leakp_previous_epoch(klass, method);
|
||||
}
|
||||
|
||||
inline traceid JfrTraceId::load_previous_epoch(const Klass* klass) {
|
||||
return JfrTraceIdLoadBarrier::load_previous_epoch(klass);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline traceid raw_load(const T* t) {
|
||||
assert(t != nullptr, "invariant");
|
||||
@ -198,6 +195,7 @@ inline void JfrTraceId::set_sticky_bit(const Method* method) {
|
||||
assert(method != nullptr, "invariant");
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
assert(!has_sticky_bit(method), "invariant");
|
||||
assert(!method->is_old(), "invariant");
|
||||
SET_METHOD_STICKY_BIT(method);
|
||||
assert(has_sticky_bit(method), "invariant");
|
||||
}
|
||||
@ -205,30 +203,22 @@ inline void JfrTraceId::set_sticky_bit(const Method* method) {
|
||||
inline void JfrTraceId::clear_sticky_bit(const Method* method) {
|
||||
assert(method != nullptr, "invarriant");
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
assert(!method->is_old(), "invariant");
|
||||
assert(JfrTraceId::has_sticky_bit(method), "invariant");
|
||||
CLEAR_STICKY_BIT_METHOD(method);
|
||||
assert(!JfrTraceId::has_sticky_bit(method), "invariant");
|
||||
}
|
||||
|
||||
inline bool JfrTraceId::has_timing_bit(const Klass* k) {
|
||||
assert(k != nullptr, "invariant");
|
||||
return HAS_TIMING_BIT(k);
|
||||
inline bool JfrTraceId::has_timing_bit(const InstanceKlass* scratch_klass) {
|
||||
assert(scratch_klass != nullptr, "invariant");
|
||||
return HAS_TIMING_BIT(scratch_klass);
|
||||
}
|
||||
|
||||
inline void JfrTraceId::set_timing_bit(const Klass* k) {
|
||||
assert(k != nullptr, "invariant");
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
assert(!has_timing_bit(k), "invariant");
|
||||
SET_TIMING_BIT(k);
|
||||
assert(has_timing_bit(k), "invariant");
|
||||
}
|
||||
|
||||
inline void JfrTraceId::clear_timing_bit(const Klass* k) {
|
||||
assert(k != nullptr, "invarriant");
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
assert(JfrTraceId::has_timing_bit(k), "invariant");
|
||||
CLEAR_TIMING_BIT(k);
|
||||
assert(!JfrTraceId::has_timing_bit(k), "invariant");
|
||||
inline void JfrTraceId::set_timing_bit(const InstanceKlass* scratch_klass) {
|
||||
assert(scratch_klass != nullptr, "invariant");
|
||||
assert(!has_timing_bit(scratch_klass), "invariant");
|
||||
SET_TIMING_BIT(scratch_klass);
|
||||
assert(has_timing_bit(scratch_klass), "invariant");
|
||||
}
|
||||
|
||||
#endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_INLINE_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2023, 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
|
||||
@ -78,7 +78,7 @@ inline uint8_t* traceid_meta_byte(const T* ptr) {
|
||||
template <>
|
||||
inline uint8_t* traceid_meta_byte<Method>(const Method* ptr) {
|
||||
assert(ptr != nullptr, "invariant");
|
||||
return ptr->trace_meta_addr();
|
||||
return ptr->trace_flags_meta_addr();
|
||||
}
|
||||
|
||||
inline uint8_t traceid_and(uint8_t bits, uint8_t current) {
|
||||
|
||||
@ -86,6 +86,27 @@ inline traceid JfrTraceIdLoadBarrier::load(const Klass* klass) {
|
||||
return TRACE_ID(klass);
|
||||
}
|
||||
|
||||
inline const Method* latest_version(const Klass* klass, const Method* method) {
|
||||
assert(klass != nullptr, "invariant");
|
||||
assert(method != nullptr, "invariant");
|
||||
assert(klass == method->method_holder(), "invariant");
|
||||
assert(method->is_old(), "invariant");
|
||||
const InstanceKlass* const ik = InstanceKlass::cast(klass);
|
||||
assert(ik->has_been_redefined(), "invariant");
|
||||
const Method* const latest_version = ik->method_with_orig_idnum(method->orig_method_idnum());
|
||||
if (latest_version == nullptr) {
|
||||
assert(AllowRedefinitionToAddDeleteMethods, "invariant");
|
||||
// method has been removed. Return old version.
|
||||
return method;
|
||||
}
|
||||
assert(latest_version != nullptr, "invariant");
|
||||
assert(latest_version != method, "invariant");
|
||||
assert(!latest_version->is_old(), "invariant");
|
||||
assert(latest_version->orig_method_idnum() == method->orig_method_idnum(), "invariant");
|
||||
assert(latest_version->name() == method->name() && latest_version->signature() == method->signature(), "invariant");
|
||||
return latest_version;
|
||||
}
|
||||
|
||||
inline traceid JfrTraceIdLoadBarrier::load(const Method* method) {
|
||||
return load(method->method_holder(), method);
|
||||
}
|
||||
@ -93,6 +114,9 @@ inline traceid JfrTraceIdLoadBarrier::load(const Method* method) {
|
||||
inline traceid JfrTraceIdLoadBarrier::load(const Klass* klass, const Method* method) {
|
||||
assert(klass != nullptr, "invariant");
|
||||
assert(method != nullptr, "invariant");
|
||||
if (method->is_old()) {
|
||||
method = latest_version(klass, method);
|
||||
}
|
||||
if (should_tag(method)) {
|
||||
SET_METHOD_AND_CLASS_USED_THIS_EPOCH(klass);
|
||||
SET_METHOD_FLAG_USED_THIS_EPOCH(method);
|
||||
@ -111,6 +135,9 @@ inline traceid JfrTraceIdLoadBarrier::load_no_enqueue(const Method* method) {
|
||||
inline traceid JfrTraceIdLoadBarrier::load_no_enqueue(const Klass* klass, const Method* method) {
|
||||
assert(klass != nullptr, "invariant");
|
||||
assert(method != nullptr, "invariant");
|
||||
if (method->is_old()) {
|
||||
method = latest_version(klass, method);
|
||||
}
|
||||
SET_METHOD_AND_CLASS_USED_THIS_EPOCH(klass);
|
||||
SET_METHOD_FLAG_USED_THIS_EPOCH(method);
|
||||
assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
|
||||
@ -123,11 +150,12 @@ inline traceid JfrTraceIdLoadBarrier::load(const ClassLoaderData* cld) {
|
||||
if (cld->has_class_mirror_holder()) {
|
||||
return 0;
|
||||
}
|
||||
const traceid id = set_used_and_get(cld);
|
||||
const Klass* const class_loader_klass = cld->class_loader_klass();
|
||||
if (class_loader_klass != nullptr) {
|
||||
load(class_loader_klass);
|
||||
}
|
||||
return set_used_and_get(cld);
|
||||
return id;
|
||||
}
|
||||
|
||||
inline traceid JfrTraceIdLoadBarrier::load(const ModuleEntry* module) {
|
||||
@ -158,6 +186,7 @@ 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 != nullptr, "invariant");
|
||||
assert(!method->is_old(), "invariant");
|
||||
assert(klass == method->method_holder(), "invariant");
|
||||
assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
|
||||
if (should_tag(method)) {
|
||||
@ -175,6 +204,7 @@ inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Metho
|
||||
inline traceid JfrTraceIdLoadBarrier::load_leakp_previous_epoch(const Klass* klass, const Method* method) {
|
||||
assert(klass != nullptr, "invariant");
|
||||
assert(method != nullptr, "invariant");
|
||||
assert(!method->is_old(), "invariant");
|
||||
assert(klass == method->method_holder(), "invariant");
|
||||
assert(METHOD_AND_CLASS_USED_PREVIOUS_EPOCH(klass), "invariant");
|
||||
if (METHOD_FLAG_NOT_USED_PREVIOUS_EPOCH(method)) {
|
||||
|
||||
@ -645,7 +645,7 @@ static void write_thread_local_buffer(JfrChunkWriter& chunkwriter, Thread* t) {
|
||||
|
||||
size_t JfrRecorderService::flush() {
|
||||
size_t total_elements = flush_metadata(_chunkwriter);
|
||||
total_elements = flush_storage(_storage, _chunkwriter);
|
||||
total_elements += flush_storage(_storage, _chunkwriter);
|
||||
if (_string_pool.is_modified()) {
|
||||
total_elements += flush_stringpool(_string_pool, _chunkwriter);
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
|
||||
#include "jfr/support/jfrThreadLocal.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
|
||||
/*
|
||||
* There are two separate repository instances.
|
||||
@ -186,6 +187,7 @@ void JfrStackTraceRepository::record_for_leak_profiler(JavaThread* current_threa
|
||||
}
|
||||
|
||||
traceid JfrStackTraceRepository::add_trace(const JfrStackTrace& stacktrace) {
|
||||
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
MutexLocker lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
|
||||
assert(stacktrace.number_of_frames() > 0, "invariant");
|
||||
const size_t index = stacktrace._hash % TABLE_SIZE;
|
||||
|
||||
@ -390,15 +390,16 @@ static inline void write_stacktraces(JfrChunkWriter& cw) {
|
||||
_resolved_list.iterate(scw);
|
||||
}
|
||||
|
||||
// First, we consolidate all stack trace blobs into a single TYPE_STACKTRACE checkpoint
|
||||
// and serialize it to the chunk. Then, all events are serialized, and unique type set blobs
|
||||
// written into the JfrCheckpoint system to be serialized to the chunk upon return.
|
||||
// First, all events are serialized, and unique type set blobs are written into the
|
||||
// JfrCheckpoint system to be serialized to the chunk upon return.
|
||||
// Then, we consolidate all stack trace blobs into a single TYPE_STACKTRACE checkpoint
|
||||
// and serialize it directly to the chunk.
|
||||
void JfrDeprecationManager::write_edges(JfrChunkWriter& cw, Thread* thread, bool on_error /* false */) {
|
||||
if (_resolved_list.is_nonempty() && JfrEventSetting::is_enabled(JfrDeprecatedInvocationEvent)) {
|
||||
write_events(cw, thread, on_error);
|
||||
if (has_stacktrace()) {
|
||||
write_stacktraces(cw);
|
||||
}
|
||||
write_events(cw, thread, on_error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -40,8 +40,6 @@
|
||||
#define EVENT_STICKY_BIT 8192
|
||||
#define IS_EVENT_KLASS(ptr) (((ptr)->trace_id() & (JDK_JFR_EVENT_KLASS | JDK_JFR_EVENT_SUBKLASS)) != 0)
|
||||
#define IS_EVENT_OR_HOST_KLASS(ptr) (((ptr)->trace_id() & (JDK_JFR_EVENT_KLASS | JDK_JFR_EVENT_SUBKLASS | EVENT_HOST_KLASS)) != 0)
|
||||
#define KLASS_HAS_STICKY_BIT(ptr) (((ptr)->trace_id() & STICKY_BIT) != 0)
|
||||
#define ON_KLASS_REDEFINITION(k, t) if (KLASS_HAS_STICKY_BIT(k)) Jfr::on_klass_redefinition(k, t)
|
||||
#define ON_KLASS_CREATION(k, p, t) Jfr::on_klass_creation(k, p, t)
|
||||
|
||||
#endif // SHARE_JFR_SUPPORT_JFRKLASSEXTENSION_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -95,11 +95,13 @@ class JfrTraceFlag {
|
||||
uint8_t* trace_flags_addr() const { \
|
||||
return _trace_flags.flags_addr(); \
|
||||
} \
|
||||
uint8_t* trace_meta_addr() const { \
|
||||
uint8_t* trace_flags_meta_addr() const { \
|
||||
return _trace_flags.meta_addr(); \
|
||||
} \
|
||||
void copy_trace_flags(uint16_t rhs_flags) const { \
|
||||
_trace_flags.set_flags(_trace_flags.flags() | rhs_flags); \
|
||||
void copy_trace_flags(const Method* rhm) const { \
|
||||
assert(rhm != nullptr, "invariant"); \
|
||||
set_trace_flags(rhm->trace_flags()); \
|
||||
assert(trace_flags()==rhm->trace_flags(), ""); \
|
||||
}
|
||||
|
||||
#endif // SHARE_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP
|
||||
|
||||
@ -36,16 +36,16 @@ class InstanceKlass;
|
||||
class JfrInstrumentedClass {
|
||||
private:
|
||||
traceid _trace_id;
|
||||
const InstanceKlass* _instance_klass;
|
||||
const InstanceKlass* _ik;
|
||||
bool _unloaded;
|
||||
|
||||
public:
|
||||
JfrInstrumentedClass(traceid trace_id = 0, const InstanceKlass* instance_klass = nullptr, bool unloaded = false) :
|
||||
_trace_id(trace_id), _instance_klass(instance_klass), _unloaded(unloaded) {
|
||||
JfrInstrumentedClass(traceid trace_id = 0, const InstanceKlass* ik = nullptr, bool unloaded = false) :
|
||||
_trace_id(trace_id), _ik(ik), _unloaded(unloaded) {
|
||||
}
|
||||
|
||||
const InstanceKlass* instance_klass() const {
|
||||
return _instance_klass;
|
||||
return _ik;
|
||||
}
|
||||
|
||||
traceid trace_id() const {
|
||||
|
||||
@ -67,6 +67,8 @@ void JfrMethodProcessor::update_methods(const InstanceKlass* ik) {
|
||||
const uint32_t idx = _methods->at(i).methods_array_index();
|
||||
Method* const method = ik_methods->at(idx);
|
||||
assert(method != nullptr, "invariant");
|
||||
assert(method->name() == _methods->at(i).name(), "invariant");
|
||||
assert(method->signature() == _methods->at(i).signature(), "invariant");
|
||||
_methods->at(i).set_method(method);
|
||||
// This is to keep the method from being unloaded during redefine / retransform.
|
||||
// Equivalent functionality to that provided by the methodHandle. Unfortunately,
|
||||
|
||||
@ -128,11 +128,11 @@ void JfrMethodTracer::retransform(JNIEnv* env, const JfrFilterClassClosure& clas
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_no_bytecode_result(const Klass* klass) {
|
||||
assert(klass != nullptr, "invariant");
|
||||
if (JfrTraceId::has_sticky_bit(klass)) {
|
||||
static void handle_no_bytecode_result(const InstanceKlass* ik) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
if (JfrTraceId::has_sticky_bit(ik)) {
|
||||
MutexLocker lock(ClassLoaderDataGraph_lock);
|
||||
JfrTraceTagging::clear_sticky_bit(InstanceKlass::cast(klass));
|
||||
JfrTraceTagging::clear_sticky(ik);
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,11 +143,11 @@ void JfrMethodTracer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& par
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
// 1. Is the ik the initial load, i.e.the first InstanceKlass, or a scratch klass, denoting a redefine / retransform?
|
||||
const Klass* const existing_klass = JfrClassTransformer::find_existing_klass(ik, THREAD);
|
||||
const bool is_retransform = existing_klass != nullptr;
|
||||
const InstanceKlass* const existing_ik = JfrClassTransformer::find_existing_klass(ik, THREAD);
|
||||
const bool is_retransform = existing_ik != nullptr;
|
||||
|
||||
// 2. Test the ik and its methods against the currently installed filter object.
|
||||
JfrMethodProcessor mp(is_retransform ? InstanceKlass::cast(existing_klass) : ik, THREAD);
|
||||
JfrMethodProcessor mp(is_retransform ? existing_ik : ik, THREAD);
|
||||
if (!mp.has_methods()) {
|
||||
return;
|
||||
}
|
||||
@ -159,7 +159,7 @@ void JfrMethodTracer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& par
|
||||
// If no bytecode is returned, either an error occurred during transformation, but more
|
||||
// likely the matched instructions were negative, i.e. instructions to remove existing instrumentation
|
||||
// and so Java added no new instrumentation. By not returning a bytecode result, the klass is restored to its original, non-instrumented, version.
|
||||
handle_no_bytecode_result(is_retransform ? InstanceKlass::cast(existing_klass) : ik);
|
||||
handle_no_bytecode_result(is_retransform ? existing_ik : ik);
|
||||
return;
|
||||
}
|
||||
// 4. Now create a new InstanceKlass representation from the modified bytecode.
|
||||
@ -173,13 +173,12 @@ void JfrMethodTracer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& par
|
||||
// Keep the original cached class file data from the existing class.
|
||||
JfrClassTransformer::transfer_cached_class_file_data(ik, new_ik, parser, THREAD);
|
||||
JfrClassTransformer::rewrite_klass_pointer(ik, new_ik, parser, THREAD); // The ik is modified to point to new_ik here.
|
||||
const InstanceKlass* const existing_ik = InstanceKlass::cast(existing_klass);
|
||||
mp.update_methods(existing_ik);
|
||||
existing_ik->module()->add_read(jdk_jfr_module());
|
||||
// By setting the sticky bit on the existng klass, we receive a callback into on_klass_redefinition (see below)
|
||||
// when our new methods are installed into the existing klass as part of retransformation / redefinition.
|
||||
// Only when we know our new methods have been installed can we add the klass to the instrumented list (done as part of callback).
|
||||
JfrTraceTagging::install_sticky_bit_for_retransform_klass(existing_ik, mp.methods(), mp.has_timing());
|
||||
JfrTraceTagging::tag_sticky_for_retransform_klass(existing_ik, ik, mp.methods(), mp.has_timing());
|
||||
return;
|
||||
}
|
||||
// Initial class load.
|
||||
@ -203,28 +202,22 @@ static inline void log_add(const InstanceKlass* ik) {
|
||||
}
|
||||
}
|
||||
|
||||
void JfrMethodTracer::add_timing_entry(const InstanceKlass* ik, traceid klass_id) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
void JfrMethodTracer::add_timing_entry(traceid klass_id) {
|
||||
assert(_timing_entries != nullptr, "invariant");
|
||||
if (JfrTraceId::has_timing_bit(ik)) {
|
||||
JfrTraceId::clear_timing_bit(ik);
|
||||
_timing_entries->append(klass_id);
|
||||
}
|
||||
_timing_entries->append(klass_id);
|
||||
}
|
||||
|
||||
// At this point we have installed our new retransformed methods into the original klass, which is ik.
|
||||
// jvmtiRedefineClassses::redefine_single_class() has finished so we are still at a safepoint.
|
||||
// If the original klass is not already in the list, add it and also dynamically tag all
|
||||
// artifacts that have the sticky bit set. If the klass has an associated TimedClass,
|
||||
// also add the klass to the list of _timing_entries for publication.
|
||||
void JfrMethodTracer::on_klass_redefinition(const InstanceKlass* ik, Thread* thread) {
|
||||
// jvmtiRedefineClassses::redefine_single_class() is about to finish so we are still at a safepoint.
|
||||
// If the original klass is not already in the list, add it. If the klass has an associated TimedClass,
|
||||
// add also the klass_id to the list of _timing_entries for publication.
|
||||
void JfrMethodTracer::on_klass_redefinition(const InstanceKlass* ik, bool has_timing) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(!ik->is_scratch_class(), "invarint");
|
||||
assert(ik->has_been_redefined(), "invariant");
|
||||
assert(JfrTraceId::has_sticky_bit(ik), "invariant");
|
||||
assert(in_use(), "invariant");
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
|
||||
const traceid klass_id = JfrTraceId::load_raw(ik);
|
||||
const JfrInstrumentedClass jic(klass_id, ik, false);
|
||||
@ -235,8 +228,9 @@ void JfrMethodTracer::on_klass_redefinition(const InstanceKlass* ik, Thread* thr
|
||||
assert(!JfrTraceIdEpoch::has_method_tracer_changed_tag_state(), "invariant");
|
||||
JfrTraceIdEpoch::set_method_tracer_tag_state();
|
||||
}
|
||||
add_timing_entry(ik, klass_id);
|
||||
JfrTraceTagging::set_dynamic_tag_for_sticky_bit(ik);
|
||||
if (has_timing) {
|
||||
add_timing_entry(klass_id);
|
||||
}
|
||||
log_add(ik);
|
||||
}
|
||||
}
|
||||
@ -258,8 +252,7 @@ void JfrMethodTracer::add_instrumented_class(InstanceKlass* ik, GrowableArray<Jf
|
||||
ik->module()->add_read(jdk_jfr_module());
|
||||
MutexLocker lock(ClassLoaderDataGraph_lock);
|
||||
assert(!in_instrumented_list(ik, instrumented_classes()), "invariant");
|
||||
JfrTraceTagging::set_dynamic_tag(ik, methods);
|
||||
JfrTraceTagging::set_sticky_bit(ik, methods);
|
||||
JfrTraceTagging::tag_sticky(ik, methods);
|
||||
const JfrInstrumentedClass jik(JfrTraceId::load_raw(ik), ik, false);
|
||||
const int idx = instrumented_classes()->append(jik);
|
||||
if (idx == 0) {
|
||||
|
||||
@ -51,7 +51,7 @@ class JfrMethodTracer: AllStatic {
|
||||
static GrowableArray<jlong>* _timing_entries; // Guarded by ClassLoaderDataGraph_lock
|
||||
|
||||
static ModuleEntry* jdk_jfr_module();
|
||||
static void add_timing_entry(const InstanceKlass* ik, traceid klass_id);
|
||||
static void add_timing_entry(traceid klass_id);
|
||||
static void retransform(JNIEnv* env, const JfrFilterClassClosure& classes, TRAPS);
|
||||
static void add_instrumented_class(InstanceKlass* ik, GrowableArray<JfrTracedMethod>* methods);
|
||||
|
||||
@ -61,7 +61,7 @@ class JfrMethodTracer: AllStatic {
|
||||
static void add_to_unloaded_set(const Klass* k);
|
||||
static void trim_instrumented_classes(bool trim);
|
||||
static GrowableArray<JfrInstrumentedClass>* instrumented_classes();
|
||||
static void on_klass_redefinition(const InstanceKlass* ik, Thread* thread);
|
||||
static void on_klass_redefinition(const InstanceKlass* ik, bool has_timing);
|
||||
static void on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS);
|
||||
static jlongArray set_filters(JNIEnv* env,
|
||||
jobjectArray classes,
|
||||
|
||||
@ -25,9 +25,11 @@
|
||||
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
|
||||
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
|
||||
#include "jfr/support/methodtracer/jfrInstrumentedClass.hpp"
|
||||
#include "jfr/support/methodtracer/jfrMethodTracer.hpp"
|
||||
#include "jfr/support/methodtracer/jfrTraceTagging.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
|
||||
void JfrTraceTagging::tag_dynamic(const InstanceKlass* ik) {
|
||||
@ -38,100 +40,39 @@ void JfrTraceTagging::tag_dynamic(const Method* method) {
|
||||
JfrTraceId::load_no_enqueue(method);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::tag_dynamic(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(methods != nullptr, "invariant");
|
||||
|
||||
for (int i = 0; i < methods->length(); ++i) {
|
||||
const Method* const method = methods->at(i).method();
|
||||
assert(method != nullptr, "invariant");
|
||||
if (!method->is_old()) {
|
||||
tag_dynamic(method);
|
||||
continue;
|
||||
}
|
||||
// A redefinition / retransformation interleaved.
|
||||
// Find and tag the latest version of the method.
|
||||
tag_dynamic(ik->method_with_orig_idnum(method->orig_method_idnum()));
|
||||
}
|
||||
}
|
||||
|
||||
void JfrTraceTagging::set_dynamic_tag(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(!ik->is_scratch_class(), "invariant");
|
||||
|
||||
tag_dynamic(ik, methods);
|
||||
tag_dynamic(ik);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::set_dynamic_tag_for_sticky_bit(const InstanceKlass* ik) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(!ik->is_scratch_class(), "invariant");
|
||||
assert(JfrTraceId::has_sticky_bit(ik), "invariant");
|
||||
|
||||
const int length = ik->methods()->length();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
const Method* const m = ik->methods()->at(i);
|
||||
if (JfrTraceId::has_sticky_bit(m)) {
|
||||
tag_dynamic(m);
|
||||
}
|
||||
}
|
||||
tag_dynamic(ik);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::tag_sticky(const InstanceKlass* ik) {
|
||||
JfrTraceId::set_sticky_bit(ik);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::tag_sticky_enqueue(const InstanceKlass* ik) {
|
||||
tag_sticky(ik);
|
||||
JfrTraceIdLoadBarrier::enqueue(ik);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::tag_sticky(const Method* method) {
|
||||
JfrTraceId::set_sticky_bit(method);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::tag_sticky(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
void JfrTraceTagging::tag_sticky(const GrowableArray<JfrTracedMethod>* methods) {
|
||||
assert(methods != nullptr, "invariant");
|
||||
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
for (int i = 0; i < methods->length(); ++i) {
|
||||
const Method* const method = methods->at(i).method();
|
||||
assert(method != nullptr, "invariant");
|
||||
if (!method->is_old()) {
|
||||
tag_sticky(method);
|
||||
continue;
|
||||
}
|
||||
// A redefinition / retransformation interleaved.
|
||||
// Find and tag the latest version of the method.
|
||||
tag_sticky(ik->method_with_orig_idnum(method->orig_method_idnum()));
|
||||
tag_sticky(method);
|
||||
}
|
||||
}
|
||||
|
||||
void JfrTraceTagging::tag_timing(const InstanceKlass* ik) {
|
||||
JfrTraceId::set_timing_bit(ik);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::install_sticky_bit_for_retransform_klass(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods, bool timing) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(!ik->is_scratch_class(), "invariant");
|
||||
|
||||
MutexLocker lock(ClassLoaderDataGraph_lock);
|
||||
if (JfrTraceId::has_sticky_bit(ik)) {
|
||||
clear_sticky_bit(ik);
|
||||
}
|
||||
tag_sticky(ik, methods);
|
||||
tag_sticky(ik);
|
||||
if (timing) {
|
||||
tag_timing(ik);
|
||||
}
|
||||
}
|
||||
|
||||
void JfrTraceTagging::set_sticky_bit(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods) {
|
||||
void JfrTraceTagging::tag_sticky(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(!ik->is_scratch_class(), "invariant");
|
||||
assert(methods != nullptr, "invariant");
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
|
||||
tag_sticky(ik, methods);
|
||||
tag_sticky(ik);
|
||||
tag_sticky(methods);
|
||||
tag_sticky_enqueue(ik);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::clear_sticky_bit(const InstanceKlass* ik, bool dynamic_tag /* true */) {
|
||||
void JfrTraceTagging::clear_sticky(const InstanceKlass* ik, bool dynamic_tag /* true */) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(!ik->is_scratch_class(), "invariant");
|
||||
assert(JfrTraceId::has_sticky_bit(ik), "invariant");
|
||||
@ -153,8 +94,78 @@ void JfrTraceTagging::clear_sticky_bit(const InstanceKlass* ik, bool dynamic_tag
|
||||
tag_dynamic(ik);
|
||||
}
|
||||
JfrTraceId::clear_sticky_bit(ik);
|
||||
if (JfrTraceId::has_timing_bit(ik)) {
|
||||
JfrTraceId::clear_timing_bit(ik);
|
||||
}
|
||||
assert(!JfrTraceId::has_timing_bit(ik), "invariant");
|
||||
}
|
||||
|
||||
void JfrTraceTagging::tag_sticky_for_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const GrowableArray<JfrTracedMethod>* methods, bool timing) {
|
||||
assert(existing_klass != nullptr, "invariant");
|
||||
assert(scratch_klass != nullptr, "invariant");
|
||||
// The scratch class has not yet received its official status.
|
||||
// assert(scratch_klass->is_scratch_class(), "invariant");
|
||||
if (timing) {
|
||||
// Can be done outside lock because it is a scratch klass.
|
||||
// Visibility guaranteed by upcoming safepoint.
|
||||
JfrTraceId::set_timing_bit(scratch_klass);
|
||||
}
|
||||
MutexLocker lock(ClassLoaderDataGraph_lock);
|
||||
if (JfrTraceId::has_sticky_bit(existing_klass)) {
|
||||
clear_sticky(existing_klass);
|
||||
}
|
||||
tag_sticky(methods);
|
||||
tag_sticky(existing_klass);
|
||||
}
|
||||
|
||||
void JfrTraceTagging::on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass) {
|
||||
assert(ik != nullptr, "invariant");
|
||||
assert(ik->has_been_redefined(), "invariant");
|
||||
assert(scratch_klass != nullptr, "invariant");
|
||||
assert(scratch_klass->is_scratch_class(), "invariant");
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
|
||||
const bool klass_has_sticky_bit = JfrTraceId::has_sticky_bit(ik);
|
||||
if (klass_has_sticky_bit) {
|
||||
JfrTraceIdLoadBarrier::enqueue(ik);
|
||||
}
|
||||
|
||||
const Array<Method*>* new_methods = ik->methods();
|
||||
assert(new_methods != nullptr, "invariant");
|
||||
|
||||
const int len = new_methods->length(); // Can be shorter, equal to, or longer than old methods length.
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
const Method* const nm = new_methods->at(i);
|
||||
assert(nm != nullptr, "invariant");
|
||||
const Method* const om = scratch_klass->method_with_orig_idnum(nm->orig_method_idnum());
|
||||
if (om == nullptr) {
|
||||
assert(AllowRedefinitionToAddDeleteMethods, "invariant");
|
||||
// nm is a newly added Method.
|
||||
continue;
|
||||
}
|
||||
assert(nm != om, "invariant");
|
||||
assert(om->is_old(), "invariant");
|
||||
assert(nm->orig_method_idnum() == om->orig_method_idnum(), "invariant");
|
||||
assert(nm->name() == om->name() && nm->signature() == om->signature(), "invariant");
|
||||
|
||||
if (nm->trace_flags() == om->trace_flags()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool is_blessed = IS_METHOD_BLESSED(nm);
|
||||
|
||||
// Copy the old method trace flags under a safepoint.
|
||||
nm->copy_trace_flags(om);
|
||||
|
||||
assert(nm->trace_flags() == om->trace_flags(), "invariant");
|
||||
|
||||
if (is_blessed) {
|
||||
BLESS_METHOD(nm);
|
||||
assert(IS_METHOD_BLESSED(nm), "invariant");
|
||||
}
|
||||
}
|
||||
|
||||
// A retransformed/redefined klass carrying the sticky bit
|
||||
// needs additional processing by the JfrMethodTracer subsystem.
|
||||
if (klass_has_sticky_bit) {
|
||||
assert(JfrMethodTracer::in_use(), "invariant");
|
||||
JfrMethodTracer::on_klass_redefinition(ik, JfrTraceId::has_timing_bit(scratch_klass));
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,18 +39,16 @@ template <typename E> class GrowableArray;
|
||||
class JfrTraceTagging : AllStatic {
|
||||
private:
|
||||
static void tag_dynamic(const InstanceKlass* ik);
|
||||
static void tag_dynamic(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods);
|
||||
static void tag_dynamic(const Method* method);
|
||||
static void tag_sticky(const InstanceKlass* ik);
|
||||
static void tag_sticky(const Method* method);
|
||||
static void tag_sticky(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods);
|
||||
static void tag_timing(const InstanceKlass* ik);
|
||||
static void tag_sticky(const GrowableArray<JfrTracedMethod>* methods);
|
||||
static void tag_sticky_enqueue(const InstanceKlass* ik);
|
||||
public:
|
||||
static void set_dynamic_tag(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods);
|
||||
static void set_dynamic_tag_for_sticky_bit(const InstanceKlass* ik);
|
||||
static void install_sticky_bit_for_retransform_klass(const InstanceKlass* existing_klass, const GrowableArray<JfrTracedMethod>* methods, bool timing);
|
||||
static void set_sticky_bit(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods);
|
||||
static void clear_sticky_bit(const InstanceKlass* ik, bool dynamic_tag = true);
|
||||
static void clear_sticky(const InstanceKlass* ik, bool dynamic_tag = true);
|
||||
static void tag_sticky(const InstanceKlass* ik, const GrowableArray<JfrTracedMethod>* methods);
|
||||
static void tag_sticky_for_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const GrowableArray<JfrTracedMethod>* methods, bool timing);
|
||||
static void on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass);
|
||||
};
|
||||
|
||||
#endif /* SHARE_JFR_SUPPORT_METHODTRACER_JFRTRACETAGGING_HPP */
|
||||
|
||||
@ -66,6 +66,9 @@
|
||||
#include "utilities/checkedCast.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfr.hpp"
|
||||
#endif
|
||||
|
||||
Array<Method*>* VM_RedefineClasses::_old_methods = nullptr;
|
||||
Array<Method*>* VM_RedefineClasses::_new_methods = nullptr;
|
||||
@ -1173,7 +1176,6 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
@ -4393,7 +4395,7 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas
|
||||
// keep track of previous versions of this class
|
||||
the_class->add_previous_version(scratch_class, emcp_method_count);
|
||||
|
||||
JFR_ONLY(ON_KLASS_REDEFINITION(the_class, current);)
|
||||
JFR_ONLY(Jfr::on_klass_redefinition(the_class, scratch_class);)
|
||||
|
||||
_timer_rsc_phase1.stop();
|
||||
if (log_is_enabled(Info, redefine, class, timer)) {
|
||||
|
||||
@ -142,7 +142,6 @@ void SafepointMechanism::process(JavaThread *thread, bool allow_suspend, bool ch
|
||||
do {
|
||||
JavaThreadState state = thread->thread_state();
|
||||
guarantee(state == _thread_in_vm, "Illegal threadstate encountered: %d", state);
|
||||
JFR_ONLY(Jfr::check_and_process_sample_request(thread);)
|
||||
if (global_poll()) {
|
||||
// Any load in ::block() must not pass the global poll load.
|
||||
// Otherwise we might load an old safepoint counter (for example).
|
||||
@ -161,6 +160,7 @@ void SafepointMechanism::process(JavaThread *thread, bool allow_suspend, bool ch
|
||||
need_rechecking = thread->handshake_state()->has_operation() && thread->handshake_state()->process_by_self(allow_suspend, check_async_exception);
|
||||
} while (need_rechecking);
|
||||
|
||||
JFR_ONLY(Jfr::check_and_process_sample_request(thread);)
|
||||
update_poll_values(thread);
|
||||
assert(sp_before == thread->last_Java_sp(), "Anchor has changed");
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ final class ConstantMap {
|
||||
if (id != 0) {
|
||||
String msg = "Missing object ID " + id + " in pool " + getName() + ". All IDs should reference an object";
|
||||
Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, msg);
|
||||
// assert false : msg;
|
||||
assert false : msg;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user