src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54623 1126f0607c70
child 58679 9c3209ff7550
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Thu Oct 17 20:53:35 2019 +0100
@@ -24,7 +24,9 @@
 
 #include "precompiled.hpp"
 #include "jfr/jni/jfrJavaSupport.hpp"
+#include "jfr/leakprofiler/leakProfiler.hpp"
 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
+#include "jfr/leakprofiler/sampling/objectSampler.hpp"
 #include "jfr/recorder/jfrRecorder.hpp"
 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
@@ -131,13 +133,13 @@
 };
 
 static int64_t write_checkpoint_event_prologue(JfrChunkWriter& cw, u8 type_id) {
-  const int64_t prev_cp_offset = cw.previous_checkpoint_offset();
-  const int64_t prev_cp_relative_offset = 0 == prev_cp_offset ? 0 : prev_cp_offset - cw.current_offset();
+  const int64_t last_cp_offset = cw.last_checkpoint_offset();
+  const int64_t delta_to_last_checkpoint = 0 == last_cp_offset ? 0 : last_cp_offset - cw.current_offset();
   cw.reserve(sizeof(u4));
   cw.write<u8>(EVENT_CHECKPOINT);
   cw.write(JfrTicks::now());
-  cw.write((int64_t)0);
-  cw.write(prev_cp_relative_offset); // write previous checkpoint offset delta
+  cw.write((int64_t)0); // duration
+  cw.write(delta_to_last_checkpoint);
   cw.write<bool>(false); // flushpoint
   cw.write((u4)1); // nof types in this checkpoint
   cw.write(type_id);
@@ -176,7 +178,7 @@
     _cw.write_padded_at_offset<u4>(number_of_elements, num_elements_offset);
     _cw.write_padded_at_offset<u4>((u4)_cw.current_offset() - current_cp_offset, current_cp_offset);
     // update writer with last checkpoint position
-    _cw.set_previous_checkpoint_offset(current_cp_offset);
+    _cw.set_last_checkpoint_offset(current_cp_offset);
     return true;
   }
 };
@@ -315,19 +317,16 @@
     vm_error = true;
     prepare_for_vm_error_rotation();
   }
+  if (!_storage.control().to_disk()) {
+    in_memory_rotation();
+  } else if (vm_error) {
+    vm_error_rotation();
+  } else {
+    chunk_rotation();
+  }
   if (msgs & (MSGBIT(MSG_STOP))) {
     stop();
   }
-  // action determined by chunkwriter state
-  if (!_chunkwriter.is_valid()) {
-    in_memory_rotation();
-    return;
-  }
-  if (vm_error) {
-    vm_error_rotation();
-    return;
-  }
-  chunk_rotation();
 }
 
 void JfrRecorderService::prepare_for_vm_error_rotation() {
@@ -335,6 +334,7 @@
     open_new_chunk(true);
   }
   _checkpoint_manager.register_service_thread(Thread::current());
+  JfrMetadataEvent::lock();
 }
 
 void JfrRecorderService::open_new_chunk(bool vm_error) {
@@ -397,7 +397,6 @@
   WriteStackTraceCheckpoint write_stack_trace_checkpoint(chunkwriter, TYPE_STACKTRACE, write_stacktrace_repo);
   write_stack_trace_checkpoint.process();
 }
-
 static void write_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
   WriteStringPool write_string_pool(string_pool);
   WriteStringPoolCheckpoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool);
@@ -418,8 +417,9 @@
 //      write checkpoint epoch transition list->
 //        write stack trace checkpoint ->
 //          write string pool checkpoint ->
-//            write storage ->
-//              release stream lock
+//            write object sample stacktraces ->
+//              write storage ->
+//                release stream lock
 //
 void JfrRecorderService::pre_safepoint_write() {
   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
@@ -428,6 +428,11 @@
   _checkpoint_manager.write_epoch_transition_mspace();
   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false);
   write_stringpool_checkpoint(_string_pool, _chunkwriter);
+  if (LeakProfiler::is_running()) {
+    // Exclusive access to the object sampler instance.
+    // The sampler is released (unlocked) later in post_safepoint_write.
+    ObjectSampleCheckpoint::on_rotation(ObjectSampler::acquire(), _stack_trace_repository);
+  }
   _storage.write();
 }
 
@@ -436,16 +441,10 @@
   VMThread::execute(&safepoint_task);
 }
 
-static void write_object_sample_stacktrace(JfrStackTraceRepository& stack_trace_repository) {
-  WriteObjectSampleStacktrace object_sample_stacktrace(stack_trace_repository);
-  object_sample_stacktrace.process();
-}
-
 //
 // safepoint write sequence
 //
 //   lock stream lock ->
-//     write object sample stacktraces ->
 //       write stacktrace repository ->
 //         write string pool ->
 //           write safepoint dependent types ->
@@ -458,7 +457,6 @@
 void JfrRecorderService::safepoint_write() {
   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
-  write_object_sample_stacktrace(_stack_trace_repository);
   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true);
   write_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter);
   _checkpoint_manager.write_safepoint_types();
@@ -478,13 +476,14 @@
 //
 // post-safepoint write sequence
 //
-//  lock stream lock ->
-//    write type set ->
-//      write checkpoints ->
-//        write metadata event ->
-//          write chunk header ->
-//            close chunk fd ->
-//              release stream lock
+//   write type set ->
+//     release object sampler ->
+//       lock stream lock ->
+//         write checkpoints ->
+//           write metadata event ->
+//             write chunk header ->
+//               close chunk fd ->
+//                 release stream lock
 //
 void JfrRecorderService::post_safepoint_write() {
   assert(_chunkwriter.is_valid(), "invariant");
@@ -493,6 +492,11 @@
   // already tagged artifacts for the previous epoch. We can accomplish this concurrently
   // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint.
   _checkpoint_manager.write_type_set();
+  if (LeakProfiler::is_running()) {
+    // The object sampler instance was exclusively acquired and locked in pre_safepoint_write.
+    // Note: There is a dependency on write_type_set() above, ensure the release is subsequent.
+    ObjectSampler::release();
+  }
   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   // serialize any outstanding checkpoint memory
   _checkpoint_manager.write();
@@ -512,11 +516,9 @@
 void JfrRecorderService::finalize_current_chunk_on_vm_error() {
   assert(_chunkwriter.is_valid(), "invariant");
   pre_safepoint_write();
-  JfrMetadataEvent::lock();
   // Do not attempt safepoint dependent operations during emergency dump.
   // Optimistically write tagged artifacts.
   _checkpoint_manager.shift_epoch();
-  _checkpoint_manager.write_type_set();
   // update time
   _chunkwriter.time_stamp_chunk_now();
   post_safepoint_write();