提交 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() {
typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation;
size_t JfrCheckpointManager::clear() {
JfrTypeSet::clear();
clear_type_set();
DiscardOperation discarder(mutexed); // mutexed discard mode
process_free_list(discarder, _free_list_mspace);
process_free_list(discarder, _epoch_transition_mspace);
......@@ -458,6 +458,16 @@ void JfrCheckpointManager::on_rotation() {
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() {
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
if (LeakProfiler::is_running()) {
......
......@@ -85,6 +85,7 @@ class JfrCheckpointManager : public JfrCHeapObj {
size_t write_threads();
size_t write_static_type_set_and_threads();
bool is_type_set_required();
void clear_type_set();
void write_type_set();
static void write_type_set_for_unloaded_classes();
......
......@@ -157,6 +157,7 @@ static void set_serialized(const T* ptr) {
assert(ptr != NULL, "invariant");
SET_SERIALIZED(ptr);
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) {
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) {
assert(cld != NULL, "invariant");
assert(!cld->is_anonymous(), "invariant");
......@@ -517,6 +538,15 @@ static void write_classloaders() {
_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) {
assert(method != NULL, "invariant");
return const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0;
......@@ -527,6 +557,7 @@ void set_serialized<Method>(MethodPtr method) {
assert(method != NULL, "invariant");
SET_METHOD_SERIALIZED(method);
assert(IS_METHOD_SERIALIZED(method), "invariant");
CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(method);
}
static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leakp) {
......@@ -759,24 +790,23 @@ static void write_symbols() {
_artifacts->tally(sw);
}
static bool clear_artifacts = false;
void JfrTypeSet::clear() {
clear_artifacts = true;
}
typedef Wrapper<KlassPtr, ClearArtifact> ClearKlassBits;
typedef Wrapper<MethodPtr, ClearArtifact> ClearMethodFlag;
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() {
assert(_artifacts != NULL, "invariant");
const size_t total_count = _artifacts->total_count();
if (previous_epoch()) {
assert(_writer != NULL, "invariant");
ClearKlassAndMethods clear(_writer);
_artifacts->iterate_klasses(clear);
JfrTypeSet::clear();
clear_klasses_and_methods();
clear_artifacts = true;
++checkpoint_id;
}
return total_count;
......@@ -815,3 +845,16 @@ size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* l
write_symbols();
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>
class ClearArtifact {
public:
bool operator()(T const& value) {
CLEAR_METHOD_AND_CLASS_PREV_EPOCH(value);
CLEAR_SERIALIZED(value);
assert(IS_NOT_SERIALIZED(value), "invariant");
SET_PREV_EPOCH_CLEARED_BIT(value);
CLEAR_METHOD_AND_CLASS_PREV_EPOCH(value);
return true;
}
};
......@@ -96,9 +97,10 @@ class ClearArtifact<const Method*> {
public:
bool operator()(const Method* method) {
assert(METHOD_FLAG_USED_PREV_EPOCH(method), "invariant");
CLEAR_METHOD_FLAG_USED_PREV_EPOCH(method);
CLEAR_METHOD_SERIALIZED(method);
assert(METHOD_NOT_SERIALIZED(method), "invariant");
SET_PREV_EPOCH_METHOD_CLEARED_BIT(method);
CLEAR_METHOD_FLAG_USED_PREV_EPOCH(method);
return true;
}
};
......
......@@ -37,6 +37,23 @@
#include "runtime/thread.inline.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>
inline traceid set_used_and_get(const T* type) {
assert(type != NULL, "invariant");
......@@ -57,14 +74,12 @@ inline traceid JfrTraceId::get(const Thread* t) {
inline traceid JfrTraceId::use(const Klass* klass) {
assert(klass != NULL, "invariant");
if (SHOULD_TAG(klass)) {
if (should_tag(klass)) {
SET_USED_THIS_EPOCH(klass);
assert(USED_THIS_EPOCH(klass), "invariant");
JfrTraceIdEpoch::set_changed_tag_state();
return get(klass);
}
assert(USED_THIS_EPOCH(klass), "invariant");
return TRACE_ID(klass);
return get(klass);
}
inline traceid JfrTraceId::use(const Method* method) {
......
......@@ -46,15 +46,19 @@
// static bits
#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 TRANSIENT_META_BIT (USED_BIT << 1)
#define TRANSIENT_META_BIT (USED_BIT << 3)
#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 TRACE_ID_SHIFT 16
#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 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)
......@@ -132,12 +136,16 @@
#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 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_LEAKP_USED(method) (METHOD_FLAG_PREDICATE(method, LEAKP_BIT))
#define METHOD_NOT_SERIALIZED(method) (!(IS_METHOD_SERIALIZED(method)))
#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 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_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
......@@ -349,26 +349,48 @@ JfrRecorderService::JfrRecorderService() :
_storage(JfrStorage::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();
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() {
return recording;
const bool is_running = recorder_state == RUNNING;
OrderAccess::loadload();
return is_running;
}
void JfrRecorderService::start() {
MutexLocker lock(JfrStream_lock);
if (LogJFR) tty->print_cr("Request to START recording");
assert(!is_recording(), "invariant");
clear();
set_recording_state(true);
assert(is_recording(), "invariant");
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() {
......@@ -394,9 +416,9 @@ void JfrRecorderService::safepoint_clear() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
_checkpoint_manager.begin_epoch_shift();
_string_pool.clear();
_stack_trace_repository.clear();
_storage.clear();
_chunkwriter.set_time_stamp();
_stack_trace_repository.clear();
_checkpoint_manager.end_epoch_shift();
}
......@@ -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() {
assert(JfrStream_lock->owned_by_self(), "invariant");
if (!_chunkwriter.is_valid()) {
......@@ -520,9 +535,9 @@ void JfrRecorderService::safepoint_write() {
write_stringpool_safepoint(_string_pool, _chunkwriter);
}
_checkpoint_manager.on_rotation();
write_stacktrace(_stack_trace_repository, _chunkwriter, true);
_storage.write_at_safepoint();
_chunkwriter.set_time_stamp();
write_stacktrace(_stack_trace_repository, _chunkwriter, true);
_checkpoint_manager.end_epoch_shift();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册