提交 cab9c7ff 编写于 作者: D Denghui Dong 提交者: D-D-H

[Backport] 8234059: Stress test fails with "Unexpected Exception in thread JFR Event Stream"

Summary:

Test Plan: jdk/jfr

Reviewed-by: yuleil

Issue: https://github.com/alibaba/dragonwell8/issues/112
上级 051d372d
...@@ -372,7 +372,7 @@ size_t JfrCheckpointManager::flush() { ...@@ -372,7 +372,7 @@ size_t JfrCheckpointManager::flush() {
typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation; typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation;
size_t JfrCheckpointManager::clear() { size_t JfrCheckpointManager::clear() {
JfrTypeSet::clear(); clear_type_set();
DiscardOperation discarder(mutexed); // mutexed discard mode DiscardOperation discarder(mutexed); // mutexed discard mode
process_free_list(discarder, _free_list_mspace); process_free_list(discarder, _free_list_mspace);
process_free_list(discarder, _epoch_transition_mspace); process_free_list(discarder, _epoch_transition_mspace);
...@@ -458,6 +458,16 @@ void JfrCheckpointManager::on_rotation() { ...@@ -458,6 +458,16 @@ void JfrCheckpointManager::on_rotation() {
notify_threads(); notify_threads();
} }
void JfrCheckpointManager::clear_type_set() {
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(!JfrRecorder::is_recording(), "invariant");
// can safepoint here
// MutexLocker cld_lock(ClassLoaderDataGraph_lock);
// MutexLocker module_lock(Module_lock);
MutexLocker package_table_lock(PackageTable_lock);
JfrTypeSet::clear();
}
void JfrCheckpointManager::write_type_set() { void JfrCheckpointManager::write_type_set() {
assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
if (LeakProfiler::is_running()) { if (LeakProfiler::is_running()) {
......
...@@ -85,6 +85,7 @@ class JfrCheckpointManager : public JfrCHeapObj { ...@@ -85,6 +85,7 @@ class JfrCheckpointManager : public JfrCHeapObj {
size_t write_threads(); size_t write_threads();
size_t write_static_type_set_and_threads(); size_t write_static_type_set_and_threads();
bool is_type_set_required(); bool is_type_set_required();
void clear_type_set();
void write_type_set(); void write_type_set();
static void write_type_set_for_unloaded_classes(); static void write_type_set_for_unloaded_classes();
......
...@@ -157,6 +157,7 @@ static void set_serialized(const T* ptr) { ...@@ -157,6 +157,7 @@ static void set_serialized(const T* ptr) {
assert(ptr != NULL, "invariant"); assert(ptr != NULL, "invariant");
SET_SERIALIZED(ptr); SET_SERIALIZED(ptr);
assert(IS_SERIALIZED(ptr), "invariant"); assert(IS_SERIALIZED(ptr), "invariant");
CLEAR_THIS_EPOCH_CLEARED_BIT(ptr);
} }
/* /*
...@@ -390,6 +391,26 @@ static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) { ...@@ -390,6 +391,26 @@ static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) {
assert(IS_NOT_SERIALIZED(value), "invariant"); assert(IS_NOT_SERIALIZED(value), "invariant");
} }
typedef JfrArtifactCallbackHost<KlassPtr, KlassArtifactRegistrator> RegistrationCallback;
static void register_klass(Klass* klass) {
assert(klass != NULL, "invariant");
assert(_subsystem_callback != NULL, "invariant");
do_previous_epoch_artifact(_subsystem_callback, klass);
}
static void do_register_klasses() {
ClassLoaderDataGraph::classes_do(&register_klass);
}
static void register_klasses() {
assert(!_artifacts->has_klass_entries(), "invariant");
KlassArtifactRegistrator reg(_artifacts);
RegistrationCallback callback(&reg);
_subsystem_callback = &callback;
do_register_klasses();
}
static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) { static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) {
assert(cld != NULL, "invariant"); assert(cld != NULL, "invariant");
assert(!cld->is_anonymous(), "invariant"); assert(!cld->is_anonymous(), "invariant");
...@@ -517,6 +538,15 @@ static void write_classloaders() { ...@@ -517,6 +538,15 @@ static void write_classloaders() {
_artifacts->tally(cldw); _artifacts->tally(cldw);
} }
typedef JfrArtifactCallbackHost<CldPtr, ClearArtifact<CldPtr> > ClearCLDCallback;
static void clear_classloaders() {
ClearArtifact<CldPtr> clear;
ClearCLDCallback callback(&clear);
_subsystem_callback = &callback;
do_class_loaders();
}
static u1 get_visibility(MethodPtr method) { static u1 get_visibility(MethodPtr method) {
assert(method != NULL, "invariant"); assert(method != NULL, "invariant");
return const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0; return const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0;
...@@ -527,6 +557,7 @@ void set_serialized<Method>(MethodPtr method) { ...@@ -527,6 +557,7 @@ void set_serialized<Method>(MethodPtr method) {
assert(method != NULL, "invariant"); assert(method != NULL, "invariant");
SET_METHOD_SERIALIZED(method); SET_METHOD_SERIALIZED(method);
assert(IS_METHOD_SERIALIZED(method), "invariant"); assert(IS_METHOD_SERIALIZED(method), "invariant");
CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(method);
} }
static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leakp) { static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leakp) {
...@@ -759,24 +790,23 @@ static void write_symbols() { ...@@ -759,24 +790,23 @@ static void write_symbols() {
_artifacts->tally(sw); _artifacts->tally(sw);
} }
static bool clear_artifacts = false;
void JfrTypeSet::clear() {
clear_artifacts = true;
}
typedef Wrapper<KlassPtr, ClearArtifact> ClearKlassBits; typedef Wrapper<KlassPtr, ClearArtifact> ClearKlassBits;
typedef Wrapper<MethodPtr, ClearArtifact> ClearMethodFlag; typedef Wrapper<MethodPtr, ClearArtifact> ClearMethodFlag;
typedef MethodIteratorHost<ClearMethodFlag, ClearKlassBits, AlwaysTrue, false> ClearKlassAndMethods; typedef MethodIteratorHost<ClearMethodFlag, ClearKlassBits, AlwaysTrue, false> ClearKlassAndMethods;
static bool clear_artifacts = false;
static void clear_klasses_and_methods() {
ClearKlassAndMethods clear(_writer);
_artifacts->iterate_klasses(clear);
}
static size_t teardown() { static size_t teardown() {
assert(_artifacts != NULL, "invariant"); assert(_artifacts != NULL, "invariant");
const size_t total_count = _artifacts->total_count(); const size_t total_count = _artifacts->total_count();
if (previous_epoch()) { if (previous_epoch()) {
assert(_writer != NULL, "invariant"); clear_klasses_and_methods();
ClearKlassAndMethods clear(_writer); clear_artifacts = true;
_artifacts->iterate_klasses(clear);
JfrTypeSet::clear();
++checkpoint_id; ++checkpoint_id;
} }
return total_count; return total_count;
...@@ -815,3 +845,16 @@ size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* l ...@@ -815,3 +845,16 @@ size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* l
write_symbols(); write_symbols();
return teardown(); return teardown();
} }
/**
* Clear all tags from the previous epoch.
*/
void JfrTypeSet::clear() {
clear_artifacts = true;
setup(NULL, NULL, false, false);
register_klasses();
// clear_packages();
// clear_modules();
clear_classloaders();
clear_klasses_and_methods();
}
...@@ -84,9 +84,10 @@ template <typename T> ...@@ -84,9 +84,10 @@ template <typename T>
class ClearArtifact { class ClearArtifact {
public: public:
bool operator()(T const& value) { bool operator()(T const& value) {
CLEAR_METHOD_AND_CLASS_PREV_EPOCH(value);
CLEAR_SERIALIZED(value); CLEAR_SERIALIZED(value);
assert(IS_NOT_SERIALIZED(value), "invariant"); assert(IS_NOT_SERIALIZED(value), "invariant");
SET_PREV_EPOCH_CLEARED_BIT(value);
CLEAR_METHOD_AND_CLASS_PREV_EPOCH(value);
return true; return true;
} }
}; };
...@@ -96,9 +97,10 @@ class ClearArtifact<const Method*> { ...@@ -96,9 +97,10 @@ class ClearArtifact<const Method*> {
public: public:
bool operator()(const Method* method) { bool operator()(const Method* method) {
assert(METHOD_FLAG_USED_PREV_EPOCH(method), "invariant"); assert(METHOD_FLAG_USED_PREV_EPOCH(method), "invariant");
CLEAR_METHOD_FLAG_USED_PREV_EPOCH(method);
CLEAR_METHOD_SERIALIZED(method); CLEAR_METHOD_SERIALIZED(method);
assert(METHOD_NOT_SERIALIZED(method), "invariant"); assert(METHOD_NOT_SERIALIZED(method), "invariant");
SET_PREV_EPOCH_METHOD_CLEARED_BIT(method);
CLEAR_METHOD_FLAG_USED_PREV_EPOCH(method);
return true; return true;
} }
}; };
......
...@@ -37,6 +37,23 @@ ...@@ -37,6 +37,23 @@
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
inline bool is_not_tagged(traceid value) {
const traceid this_epoch_bit = JfrTraceIdEpoch::in_use_this_epoch_bit();
return (value & ((this_epoch_bit << META_SHIFT) | this_epoch_bit)) != this_epoch_bit;
}
template <typename T>
inline bool should_tag(const T* t) {
assert(t != NULL, "invariant");
return is_not_tagged(TRACE_ID_RAW(t));
}
template <>
inline bool should_tag<Method>(const Method* method) {
assert(method != NULL, "invariant");
return is_not_tagged((traceid)method->trace_flags());
}
template <typename T> template <typename T>
inline traceid set_used_and_get(const T* type) { inline traceid set_used_and_get(const T* type) {
assert(type != NULL, "invariant"); assert(type != NULL, "invariant");
...@@ -57,14 +74,12 @@ inline traceid JfrTraceId::get(const Thread* t) { ...@@ -57,14 +74,12 @@ inline traceid JfrTraceId::get(const Thread* t) {
inline traceid JfrTraceId::use(const Klass* klass) { inline traceid JfrTraceId::use(const Klass* klass) {
assert(klass != NULL, "invariant"); assert(klass != NULL, "invariant");
if (SHOULD_TAG(klass)) { if (should_tag(klass)) {
SET_USED_THIS_EPOCH(klass); SET_USED_THIS_EPOCH(klass);
assert(USED_THIS_EPOCH(klass), "invariant");
JfrTraceIdEpoch::set_changed_tag_state(); JfrTraceIdEpoch::set_changed_tag_state();
return get(klass);
} }
assert(USED_THIS_EPOCH(klass), "invariant"); assert(USED_THIS_EPOCH(klass), "invariant");
return TRACE_ID(klass); return get(klass);
} }
inline traceid JfrTraceId::use(const Method* method) { inline traceid JfrTraceId::use(const Method* method) {
......
...@@ -46,15 +46,19 @@ ...@@ -46,15 +46,19 @@
// static bits // static bits
#define META_SHIFT 8 #define META_SHIFT 8
#define LEAKP_META_BIT USED_BIT #define EPOCH_1_CLEARED_META_BIT USED_BIT
#define EPOCH_1_CLEARED_BIT (EPOCH_1_CLEARED_META_BIT << META_SHIFT)
#define EPOCH_2_CLEARED_META_BIT (USED_BIT << 1)
#define EPOCH_2_CLEARED_BIT (EPOCH_2_CLEARED_META_BIT << META_SHIFT)
#define LEAKP_META_BIT (USED_BIT << 2)
#define LEAKP_BIT (LEAKP_META_BIT << META_SHIFT) #define LEAKP_BIT (LEAKP_META_BIT << META_SHIFT)
#define TRANSIENT_META_BIT (USED_BIT << 1) #define TRANSIENT_META_BIT (USED_BIT << 3)
#define TRANSIENT_BIT (TRANSIENT_META_BIT << META_SHIFT) #define TRANSIENT_BIT (TRANSIENT_META_BIT << META_SHIFT)
#define SERIALIZED_META_BIT (USED_BIT << 2) #define SERIALIZED_META_BIT (USED_BIT << 4)
#define SERIALIZED_BIT (SERIALIZED_META_BIT << META_SHIFT) #define SERIALIZED_BIT (SERIALIZED_META_BIT << META_SHIFT)
#define TRACE_ID_SHIFT 16 #define TRACE_ID_SHIFT 16
#define METHOD_ID_NUM_MASK ((1 << TRACE_ID_SHIFT) - 1) #define METHOD_ID_NUM_MASK ((1 << TRACE_ID_SHIFT) - 1)
#define META_BITS (SERIALIZED_BIT | TRANSIENT_BIT | LEAKP_BIT) #define META_BITS (SERIALIZED_BIT | TRANSIENT_BIT | LEAKP_BIT | EPOCH_2_CLEARED_BIT | EPOCH_1_CLEARED_BIT)
#define EVENT_BITS (EVENT_HOST_KLASS | JDK_JFR_EVENT_KLASS | JDK_JFR_EVENT_SUBKLASS) #define EVENT_BITS (EVENT_HOST_KLASS | JDK_JFR_EVENT_KLASS | JDK_JFR_EVENT_SUBKLASS)
#define USED_BITS (METHOD_USED_EPOCH_2_BIT | METHOD_USED_EPOCH_1_BIT | USED_EPOCH_2_BIT | USED_EPOCH_1_BIT) #define USED_BITS (METHOD_USED_EPOCH_2_BIT | METHOD_USED_EPOCH_1_BIT | USED_EPOCH_2_BIT | USED_EPOCH_1_BIT)
#define ALL_BITS (META_BITS | EVENT_BITS | USED_BITS) #define ALL_BITS (META_BITS | EVENT_BITS | USED_BITS)
...@@ -132,12 +136,16 @@ ...@@ -132,12 +136,16 @@
#define SHOULD_TAG_KLASS_METHOD(ptr) (METHOD_NOT_USED_THIS_EPOCH(ptr)) #define SHOULD_TAG_KLASS_METHOD(ptr) (METHOD_NOT_USED_THIS_EPOCH(ptr))
#define SET_SERIALIZED(ptr) (TRACE_ID_META_TAG(ptr, SERIALIZED_META_BIT)) #define SET_SERIALIZED(ptr) (TRACE_ID_META_TAG(ptr, SERIALIZED_META_BIT))
#define CLEAR_SERIALIZED(ptr) (TRACE_ID_META_CLEAR(ptr, META_MASK)) #define CLEAR_SERIALIZED(ptr) (TRACE_ID_META_CLEAR(ptr, META_MASK))
#define SET_PREV_EPOCH_CLEARED_BIT(ptr) (TRACE_ID_META_TAG(ptr, IN_USE_PREV_EPOCH_BIT))
#define IS_METHOD_SERIALIZED(method) (METHOD_FLAG_PREDICATE(method, SERIALIZED_BIT)) #define IS_METHOD_SERIALIZED(method) (METHOD_FLAG_PREDICATE(method, SERIALIZED_BIT))
#define IS_METHOD_LEAKP_USED(method) (METHOD_FLAG_PREDICATE(method, LEAKP_BIT)) #define IS_METHOD_LEAKP_USED(method) (METHOD_FLAG_PREDICATE(method, LEAKP_BIT))
#define METHOD_NOT_SERIALIZED(method) (!(IS_METHOD_SERIALIZED(method))) #define METHOD_NOT_SERIALIZED(method) (!(IS_METHOD_SERIALIZED(method)))
#define SET_METHOD_LEAKP(method) (METHOD_META_TAG(method, LEAKP_META_BIT)) #define SET_METHOD_LEAKP(method) (METHOD_META_TAG(method, LEAKP_META_BIT))
#define SET_METHOD_SERIALIZED(method) (METHOD_META_TAG(method, SERIALIZED_META_BIT)) #define SET_METHOD_SERIALIZED(method) (METHOD_META_TAG(method, SERIALIZED_META_BIT))
#define CLEAR_METHOD_SERIALIZED(method) (METHOD_META_CLEAR(method, META_MASK)) #define CLEAR_METHOD_SERIALIZED(method) (METHOD_META_CLEAR(method, META_MASK))
#define SET_PREV_EPOCH_METHOD_CLEARED_BIT(ptr) (METHOD_META_TAG(ptr, IN_USE_PREV_EPOCH_BIT))
#define CLEAR_LEAKP(ptr) (TRACE_ID_META_CLEAR(ptr, (~(LEAKP_META_BIT)))) #define CLEAR_LEAKP(ptr) (TRACE_ID_META_CLEAR(ptr, (~(LEAKP_META_BIT))))
#define CLEAR_THIS_EPOCH_CLEARED_BIT(ptr) (TRACE_ID_META_CLEAR(ptr,(~(IN_USE_THIS_EPOCH_BIT))))
#define CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(ptr) (METHOD_META_CLEAR(ptr,(~(IN_USE_THIS_EPOCH_BIT))))
#endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDMACROS_HPP #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDMACROS_HPP
...@@ -349,26 +349,48 @@ JfrRecorderService::JfrRecorderService() : ...@@ -349,26 +349,48 @@ JfrRecorderService::JfrRecorderService() :
_storage(JfrStorage::instance()), _storage(JfrStorage::instance()),
_string_pool(JfrStringPool::instance()) {} _string_pool(JfrStringPool::instance()) {}
static bool recording = false; enum RecorderState {
STOPPED,
RUNNING
};
static RecorderState recorder_state = STOPPED;
static void set_recording_state(bool is_recording) { static void set_recorder_state(RecorderState from, RecorderState to) {
assert(from == recorder_state, "invariant");
OrderAccess::storestore(); OrderAccess::storestore();
recording = is_recording; recorder_state = to;
}
static void start_recorder() {
set_recorder_state(STOPPED, RUNNING);
if (LogJFR) tty->print_cr("Recording service STARTED");
}
static void stop_recorder() {
set_recorder_state(RUNNING, STOPPED);
if (LogJFR) tty->print_cr("Recording service STOPPED");
} }
bool JfrRecorderService::is_recording() { bool JfrRecorderService::is_recording() {
return recording; const bool is_running = recorder_state == RUNNING;
OrderAccess::loadload();
return is_running;
} }
void JfrRecorderService::start() { void JfrRecorderService::start() {
MutexLocker lock(JfrStream_lock); MutexLocker lock(JfrStream_lock);
if (LogJFR) tty->print_cr("Request to START recording");
assert(!is_recording(), "invariant"); assert(!is_recording(), "invariant");
clear(); clear();
set_recording_state(true);
assert(is_recording(), "invariant");
open_new_chunk(); open_new_chunk();
if (LogJFR) tty->print_cr("Recording STARTED"); start_recorder();
assert(is_recording(), "invariant");
}
static void stop() {
assert(JfrRecorderService::is_recording(), "invariant");
stop_recorder();
assert(!JfrRecorderService::is_recording(), "invariant");
} }
void JfrRecorderService::clear() { void JfrRecorderService::clear() {
...@@ -394,9 +416,9 @@ void JfrRecorderService::safepoint_clear() { ...@@ -394,9 +416,9 @@ void JfrRecorderService::safepoint_clear() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant"); assert(SafepointSynchronize::is_at_safepoint(), "invariant");
_checkpoint_manager.begin_epoch_shift(); _checkpoint_manager.begin_epoch_shift();
_string_pool.clear(); _string_pool.clear();
_stack_trace_repository.clear();
_storage.clear(); _storage.clear();
_chunkwriter.set_time_stamp(); _chunkwriter.set_time_stamp();
_stack_trace_repository.clear();
_checkpoint_manager.end_epoch_shift(); _checkpoint_manager.end_epoch_shift();
} }
...@@ -413,13 +435,6 @@ void JfrRecorderService::open_new_chunk(bool vm_error) { ...@@ -413,13 +435,6 @@ void JfrRecorderService::open_new_chunk(bool vm_error) {
} }
} }
static void stop() {
assert(JfrRecorderService::is_recording(), "invariant");
if (LogJFR) tty->print_cr("Recording STOPPED");
set_recording_state(false);
assert(!JfrRecorderService::is_recording(), "invariant");
}
void JfrRecorderService::prepare_for_vm_error_rotation() { void JfrRecorderService::prepare_for_vm_error_rotation() {
assert(JfrStream_lock->owned_by_self(), "invariant"); assert(JfrStream_lock->owned_by_self(), "invariant");
if (!_chunkwriter.is_valid()) { if (!_chunkwriter.is_valid()) {
...@@ -520,9 +535,9 @@ void JfrRecorderService::safepoint_write() { ...@@ -520,9 +535,9 @@ void JfrRecorderService::safepoint_write() {
write_stringpool_safepoint(_string_pool, _chunkwriter); write_stringpool_safepoint(_string_pool, _chunkwriter);
} }
_checkpoint_manager.on_rotation(); _checkpoint_manager.on_rotation();
write_stacktrace(_stack_trace_repository, _chunkwriter, true);
_storage.write_at_safepoint(); _storage.write_at_safepoint();
_chunkwriter.set_time_stamp(); _chunkwriter.set_time_stamp();
write_stacktrace(_stack_trace_repository, _chunkwriter, true);
_checkpoint_manager.end_epoch_shift(); _checkpoint_manager.end_epoch_shift();
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册