src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
branchJEP-349-branch
changeset 57882 562f598d303c
parent 57873 68134337dbf8
child 57886 87f8a814310d
--- 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();
 }