--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp Mon Aug 26 17:59:32 2019 +0200
@@ -181,8 +181,20 @@
return lease_free(size, manager._free_list_mspace, lease_retry, thread);
}
+JfrCheckpointMspace* JfrCheckpointManager::lookup(BufferPtr old) const {
+ assert(old != NULL, "invariant");
+ return _free_list_mspace->in_free_list(old) ? _free_list_mspace : _epoch_transition_mspace;
+}
+
+BufferPtr JfrCheckpointManager::lease_buffer(BufferPtr old, Thread* thread, size_t size /* 0 */) {
+ assert(old != NULL, "invariant");
+ JfrCheckpointMspace* mspace = instance().lookup(old);
+ assert(mspace != NULL, "invariant");
+ return lease_free(size, mspace, lease_retry, thread);
+}
+
/*
-* If the buffer was a "lease" from the free list, release back.
+* If the buffer was a "lease", release back.
*
* The buffer is effectively invalidated for the thread post-return,
* and the caller should take means to ensure that it is not referenced.
@@ -202,7 +214,7 @@
return NULL;
}
// migration of in-flight information
- BufferPtr const new_buffer = lease_buffer(thread, used + requested);
+ BufferPtr const new_buffer = lease_buffer(old, thread, used + requested);
if (new_buffer != NULL) {
migrate_outstanding_writes(old, new_buffer, used, requested);
}
@@ -213,8 +225,8 @@
// offsets into the JfrCheckpointEntry
static const juint starttime_offset = sizeof(jlong);
static const juint duration_offset = starttime_offset + sizeof(jlong);
-static const juint flushpoint_offset = duration_offset + sizeof(jlong);
-static const juint types_offset = flushpoint_offset + sizeof(juint);
+static const juint mode_offset = duration_offset + sizeof(jlong);
+static const juint types_offset = mode_offset + sizeof(juint);
static const juint payload_offset = types_offset + sizeof(juint);
template <typename Return>
@@ -234,6 +246,10 @@
return read_data<jlong>(data + duration_offset);
}
+static u1 mode(const u1* data) {
+ return read_data<u1>(data + mode_offset);
+}
+
static juint number_of_types(const u1* data) {
return read_data<juint>(data + types_offset);
}
@@ -241,11 +257,11 @@
static void write_checkpoint_header(JfrChunkWriter& cw, int64_t offset_prev_cp_event, const u1* data) {
cw.reserve(sizeof(u4));
cw.write<u8>(EVENT_CHECKPOINT);
- cw.write<u8>(starttime(data));
- cw.write<u8>(duration(data));
- cw.write<u8>(offset_prev_cp_event);
- cw.write<bool>(false); // not a flushpoint
- cw.write<juint>(number_of_types(data));
+ cw.write(starttime(data));
+ cw.write(duration(data));
+ cw.write(offset_prev_cp_event);
+ cw.write(mode(data));
+ cw.write(number_of_types(data));
}
static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) {
@@ -350,28 +366,44 @@
return wo.processed();
}
+// Optimization for write_types() and write_threads() is to write
+// directly into the epoch transition mspace because we will immediately
+// serialize and reset this mspace post-write.
+static JfrBuffer* get_epoch_transition_buffer(JfrCheckpointMspace* mspace, Thread* t) {
+ assert(mspace != NULL, "invariant");
+ JfrBuffer* const buffer = mspace->free_head();
+ assert(buffer != NULL, "invariant");
+ buffer->acquire(t);
+ buffer->set_lease();
+ DEBUG_ONLY(assert_free_lease(buffer);)
+ return buffer;
+}
+
size_t JfrCheckpointManager::write_types() {
ResourceMark rm;
HandleMark hm;
Thread* const t = Thread::current();
- // Optimization here is to write the types directly into the epoch transition mspace
- // because the caller will immediately serialize and reset this mspace.
- JfrBuffer* const buffer = _epoch_transition_mspace->free_tail();
- assert(buffer != NULL, "invariant");
- buffer->acquire(t);
- buffer->set_lease();
- DEBUG_ONLY(assert_free_lease(buffer);)
- JfrCheckpointWriter writer(t, buffer);
+ JfrCheckpointWriter writer(t, get_epoch_transition_buffer(_epoch_transition_mspace, t), STATICS);
JfrTypeManager::write_types(writer);
return writer.used_size();
}
+size_t JfrCheckpointManager::write_threads() {
+ ResourceMark rm;
+ HandleMark hm;
+ Thread* const t = Thread::current();
+ JfrCheckpointWriter writer(t, get_epoch_transition_buffer(_epoch_transition_mspace, t), THREADS);
+ JfrTypeManager::write_threads(writer);
+ return writer.used_size();
+}
+
size_t JfrCheckpointManager::write_epoch_transition_mspace() {
return write_mspace<ExclusiveOp, CompositeOperation>(_epoch_transition_mspace, _chunkwriter);
}
size_t JfrCheckpointManager::write_constants() {
write_types();
+ write_threads();
return write_epoch_transition_mspace();
}
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp Mon Aug 26 17:59:32 2019 +0200
@@ -68,7 +68,10 @@
void unlock();
DEBUG_ONLY(bool is_locked() const;)
+ JfrCheckpointMspace* lookup(Buffer* old) const;
+
static Buffer* lease_buffer(Thread* t, size_t size = 0);
+ static Buffer* lease_buffer(Buffer* old, Thread* t, size_t size = 0);
static Buffer* flush(Buffer* old, size_t used, size_t requested, Thread* t);
size_t clear();
@@ -77,6 +80,7 @@
size_t flush();
size_t write_epoch_transition_mspace();
size_t write_types();
+ size_t write_threads();
size_t write_metadata_event();
void write_type_set();
void shift_epoch();
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp Mon Aug 26 17:59:32 2019 +0200
@@ -30,11 +30,12 @@
JfrCheckpointFlush::JfrCheckpointFlush(Type* old, size_t used, size_t requested, Thread* t) :
_result(JfrCheckpointManager::flush(old, used, requested, t)) {}
-JfrCheckpointWriter::JfrCheckpointWriter() :
+JfrCheckpointWriter::JfrCheckpointWriter(JfrCheckpointMode mode /* NORMAL */) :
JfrCheckpointWriterBase(JfrCheckpointManager::lease_buffer(Thread::current()), Thread::current()),
_time(JfrTicks::now()),
_offset(0),
_count(0),
+ _mode(mode),
_header(true) {
assert(this->is_acquired(), "invariant");
assert(0 == this->current_offset(), "invariant");
@@ -43,11 +44,12 @@
}
}
-JfrCheckpointWriter::JfrCheckpointWriter(Thread* t, bool header /* true */) :
+JfrCheckpointWriter::JfrCheckpointWriter(Thread* t, bool header /* true */, JfrCheckpointMode mode /* NORMAL */) :
JfrCheckpointWriterBase(JfrCheckpointManager::lease_buffer(t), t),
_time(JfrTicks::now()),
_offset(0),
_count(0),
+ _mode(mode),
_header(header) {
assert(this->is_acquired(), "invariant");
assert(0 == this->current_offset(), "invariant");
@@ -56,11 +58,12 @@
}
}
-JfrCheckpointWriter::JfrCheckpointWriter(Thread* t, JfrBuffer* buffer) :
+JfrCheckpointWriter::JfrCheckpointWriter(Thread* t, JfrBuffer* buffer, JfrCheckpointMode mode /* NORMAL */) :
JfrCheckpointWriterBase(buffer, t),
_time(JfrTicks::now()),
_offset(0),
_count(0),
+ _mode(mode),
_header(true) {
assert(this->is_acquired(), "invariant");
assert(0 == this->current_offset(), "invariant");
@@ -69,13 +72,13 @@
}
}
-static void write_checkpoint_header(u1* pos, int64_t size, jlong time, u4 type_count) {
+static void write_checkpoint_header(u1* pos, int64_t size, jlong time, u4 mode, u4 type_count) {
assert(pos != NULL, "invariant");
JfrBigEndianWriter be_writer(pos, sizeof(JfrCheckpointEntry));
be_writer.write(size);
be_writer.write(time);
be_writer.write(JfrTicks::now().value() - time);
- be_writer.write((u4)0); // not a flushpoint
+ be_writer.write(mode);
be_writer.write(type_count);
assert(be_writer.is_valid(), "invariant");
}
@@ -98,7 +101,7 @@
assert(this->used_size() > sizeof(JfrCheckpointEntry), "invariant");
const int64_t size = this->current_offset();
assert(size + this->start_pos() == this->current_pos(), "invariant");
- write_checkpoint_header(const_cast<u1*>(this->start_pos()), size, _time, count());
+ write_checkpoint_header(const_cast<u1*>(this->start_pos()), size, _time, _mode, count());
release();
}
@@ -156,7 +159,7 @@
}
*size = this->used_size();
assert(this->start_pos() + *size == this->current_pos(), "invariant");
- write_checkpoint_header(const_cast<u1*>(this->start_pos()), this->used_offset(), _time, count());
+ write_checkpoint_header(const_cast<u1*>(this->start_pos()), this->used_offset(), _time, _mode, count());
_header = false; // the header is already written
if (move) {
this->seek(_offset);
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp Mon Aug 26 17:59:32 2019 +0200
@@ -60,6 +60,7 @@
JfrTicks _time;
int64_t _offset;
u4 _count;
+ JfrCheckpointMode _mode;
bool _header;
u4 count() const;
@@ -67,10 +68,10 @@
void increment();
const u1* session_data(size_t* size, bool move = false, const JfrCheckpointContext* ctx = NULL);
void release();
- JfrCheckpointWriter(Thread* t, JfrBuffer* buffer);
+ JfrCheckpointWriter(Thread* t, JfrBuffer* buffer, JfrCheckpointMode mode = NORMAL);
public:
- JfrCheckpointWriter();
- JfrCheckpointWriter(Thread* t, bool header = true);
+ JfrCheckpointWriter(JfrCheckpointMode mode = NORMAL);
+ JfrCheckpointWriter(Thread* t, bool header = true, JfrCheckpointMode mode = NORMAL);
~JfrCheckpointWriter();
void write_type(JfrTypeId type_id);
void write_count(u4 nof_entries);
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp Mon Aug 26 17:59:32 2019 +0200
@@ -141,6 +141,23 @@
}
}
+static void serialize_threads(JfrCheckpointWriter& writer) {
+ JfrThreadConstantSet thread_set;
+ writer.write_type(TYPE_THREAD);
+ thread_set.serialize(writer);
+}
+
+static void serialize_thread_groups(JfrCheckpointWriter& writer) {
+ JfrThreadGroupConstant thread_group_set;
+ writer.write_type(TYPE_THREADGROUP);
+ thread_group_set.serialize(writer);
+}
+
+void JfrTypeManager::write_threads(JfrCheckpointWriter& writer) {
+ serialize_threads(writer);
+ serialize_thread_groups(writer);
+}
+
void JfrTypeManager::notify_types_on_rotation() {
const Iterator iter(types);
while (iter.has_next()) {
@@ -180,7 +197,7 @@
ResourceMark rm(t);
HandleMark hm(t);
JfrThreadConstant type_thread(t);
- JfrCheckpointWriter writer(t);
+ JfrCheckpointWriter writer(t, true, THREADS);
writer.write_type(TYPE_THREAD);
type_thread.serialize(writer);
// create and install a checkpoint blob
@@ -193,7 +210,7 @@
ResourceMark rm(t);
HandleMark hm(t);
JfrThreadConstant type_thread(t);
- JfrCheckpointWriter writer(t);
+ JfrCheckpointWriter writer(t, true, THREADS);
writer.write_type(TYPE_THREAD);
type_thread.serialize(writer);
}
@@ -227,10 +244,6 @@
bool JfrTypeManager::initialize() {
SerializerRegistrationGuard guard;
-
- // register non-safepointing type serialization
- register_type(TYPE_THREADGROUP, false, new JfrThreadGroupConstant());
- register_type(TYPE_THREAD, false, new JfrThreadConstantSet());
register_type(TYPE_FLAGVALUEORIGIN, true, new FlagValueOriginConstant());
register_type(TYPE_INFLATECAUSE, true, new MonitorInflateCauseConstant());
register_type(TYPE_GCCAUSE, true, new GCCauseConstant());
@@ -247,7 +260,6 @@
register_type(TYPE_CODEBLOBTYPE, true, new CodeBlobTypeConstant());
register_type(TYPE_VMOPERATIONTYPE, true, new VMOperationTypeConstant());
register_type(TYPE_THREADSTATE, true, new ThreadStateConstant());
-
return true;
}
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.hpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.hpp Mon Aug 26 17:59:32 2019 +0200
@@ -34,6 +34,7 @@
static bool initialize();
static void clear();
static void write_types(JfrCheckpointWriter& writer);
+ static void write_threads(JfrCheckpointWriter& writer);
static void notify_types_on_rotation();
static void write_type_set();
static void write_type_set_for_unloaded_classes();
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp Mon Aug 26 17:59:32 2019 +0200
@@ -183,14 +183,14 @@
}
};
-static void write_checkpoint_header(JfrChunkWriter& cw, int64_t event_offset, bool flushpoint) {
+static void write_checkpoint_header(JfrChunkWriter& cw, int64_t event_offset, u1 mode) {
const int64_t delta = cw.last_checkpoint_offset() == 0 ? 0 : cw.last_checkpoint_offset() - event_offset;
cw.reserve(sizeof(u4));
cw.write<u8>(EVENT_CHECKPOINT);
cw.write<u8>(JfrTicks::now().value());
cw.write<u8>(0); // duration
cw.write<u8>(delta); // to previous checkpoint
- cw.write<bool>(flushpoint);
+ cw.write<u1>(mode);
cw.write<u4>(1); // pool count
cw.write<u8>(TYPE_CHUNKHEADER);
cw.write<u4>(1); // count
@@ -201,7 +201,8 @@
int64_t JfrChunkWriter::write_chunk_header_checkpoint(bool flushpoint) {
assert(this->has_valid_fd(), "invariant");
const int64_t event_size_offset = current_offset();
- write_checkpoint_header(*this, event_size_offset, flushpoint);
+ const u1 mode = flushpoint ? FLUSH | HEADER : HEADER;
+ write_checkpoint_header(*this, event_size_offset, mode);
const int64_t start_offset = current_offset();
JfrChunkHeadWriter head(this, start_offset, false);
head.write_magic();
--- a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.hpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.hpp Mon Aug 26 17:59:32 2019 +0200
@@ -99,8 +99,8 @@
template <typename IteratorCallback, typename IteratorType>
void iterate(IteratorCallback& callback, bool full = true, jfr_iter_direction direction = forward);
- debug_only(bool in_full_list(const Type* t) const { return _full.in_list(t); })
- debug_only(bool in_free_list(const Type* t) const { return _free.in_list(t); })
+ bool in_full_list(const Type* t) const { return _full.in_list(t); }
+ bool in_free_list(const Type* t) const { return _free.in_list(t); }
};
#endif // SHARE_JFR_RECORDER_STORAGE_JFRMEMORYSPACE_HPP
--- a/src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp Mon Aug 26 17:59:32 2019 +0200
@@ -48,8 +48,8 @@
void prepend(T* const node);
void append(T* const node);
void append_list(T* const head_node, T* const tail_node, size_t count);
- debug_only(bool in_list(const T* const target_node) const;)
- debug_only(bool locate(const T* start_node, const T* const target_node) const;)
+ bool in_list(const T* const target_node) const;
+ bool locate(const T* start_node, const T* const target_node) const;
};
template <typename T>
@@ -153,7 +153,6 @@
return node;
}
-#ifdef ASSERT
template <typename T>
bool JfrDoublyLinkedList<T>::locate(const T* node, const T* const target) const {
assert(target != NULL, "invariant");
@@ -182,7 +181,6 @@
}
assert(count_param == count, "invariant");
}
-#endif // ASSERT
template <typename T>
void JfrDoublyLinkedList<T>::append_list(T* const head_node, T* const tail_node, size_t count) {
--- a/src/hotspot/share/jfr/utilities/jfrTypes.hpp Mon Aug 26 13:09:14 2019 +0200
+++ b/src/hotspot/share/jfr/utilities/jfrTypes.hpp Mon Aug 26 17:59:32 2019 +0200
@@ -76,4 +76,12 @@
TIMED
};
+enum JfrCheckpointMode : u1 {
+ NORMAL,
+ FLUSH,
+ HEADER,
+ STATICS = 4,
+ THREADS = 8
+};
+
#endif // SHARE_JFR_UTILITIES_JFRTYPES_HPP