checkpoint bit pattern JEP-349-branch
authormgronlun
Mon, 26 Aug 2019 17:59:32 +0200
branchJEP-349-branch
changeset 57882 562f598d303c
parent 57878 bffba8d6611a
child 57883 90e867ac8c37
checkpoint bit pattern
src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp
src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp
src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp
src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp
src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.hpp
src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp
src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.hpp
src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp
src/hotspot/share/jfr/utilities/jfrTypes.hpp
--- 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