diff -r 13588c901957 -r 9cf78a70fa4f src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp --- 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(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(false); // flushpoint cw.write((u4)1); // nof types in this checkpoint cw.write(type_id); @@ -176,7 +178,7 @@ _cw.write_padded_at_offset(number_of_elements, num_elements_offset); _cw.write_padded_at_offset((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();