22 * |
22 * |
23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "jfr/jni/jfrJavaSupport.hpp" |
26 #include "jfr/jni/jfrJavaSupport.hpp" |
|
27 #include "jfr/leakprofiler/leakProfiler.hpp" |
27 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp" |
28 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp" |
|
29 #include "jfr/leakprofiler/sampling/objectSampler.hpp" |
28 #include "jfr/recorder/jfrRecorder.hpp" |
30 #include "jfr/recorder/jfrRecorder.hpp" |
29 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" |
31 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" |
30 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp" |
32 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp" |
31 #include "jfr/recorder/repository/jfrChunkRotation.hpp" |
33 #include "jfr/recorder/repository/jfrChunkRotation.hpp" |
32 #include "jfr/recorder/repository/jfrChunkWriter.hpp" |
34 #include "jfr/recorder/repository/jfrChunkWriter.hpp" |
332 void JfrRecorderService::prepare_for_vm_error_rotation() { |
334 void JfrRecorderService::prepare_for_vm_error_rotation() { |
333 if (!_chunkwriter.is_valid()) { |
335 if (!_chunkwriter.is_valid()) { |
334 open_new_chunk(true); |
336 open_new_chunk(true); |
335 } |
337 } |
336 _checkpoint_manager.register_service_thread(Thread::current()); |
338 _checkpoint_manager.register_service_thread(Thread::current()); |
|
339 JfrMetadataEvent::lock(); |
337 } |
340 } |
338 |
341 |
339 void JfrRecorderService::open_new_chunk(bool vm_error) { |
342 void JfrRecorderService::open_new_chunk(bool vm_error) { |
340 assert(!_chunkwriter.is_valid(), "invariant"); |
343 assert(!_chunkwriter.is_valid(), "invariant"); |
341 assert(!JfrStream_lock->owned_by_self(), "invariant"); |
344 assert(!JfrStream_lock->owned_by_self(), "invariant"); |
395 WriteStackTraceRepository write_stacktrace_repo(stack_trace_repo, chunkwriter, clear); |
398 WriteStackTraceRepository write_stacktrace_repo(stack_trace_repo, chunkwriter, clear); |
396 WriteStackTraceCheckpoint write_stack_trace_checkpoint(chunkwriter, TYPE_STACKTRACE, write_stacktrace_repo); |
399 WriteStackTraceCheckpoint write_stack_trace_checkpoint(chunkwriter, TYPE_STACKTRACE, write_stacktrace_repo); |
397 write_stack_trace_checkpoint.process(); |
400 write_stack_trace_checkpoint.process(); |
398 } |
401 } |
399 |
402 |
|
403 static void write_object_sample_stacktrace(ObjectSampler* sampler, JfrStackTraceRepository& stack_trace_repository) { |
|
404 WriteObjectSampleStacktrace object_sample_stacktrace(sampler, stack_trace_repository); |
|
405 object_sample_stacktrace.process(); |
|
406 } |
|
407 |
400 static void write_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) { |
408 static void write_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) { |
401 WriteStringPool write_string_pool(string_pool); |
409 WriteStringPool write_string_pool(string_pool); |
402 WriteStringPoolCheckpoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool); |
410 WriteStringPoolCheckpoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool); |
403 write_string_pool_checkpoint.process(); |
411 write_string_pool_checkpoint.process(); |
404 } |
412 } |
415 // lock stream lock -> |
423 // lock stream lock -> |
416 // write non-safepoint dependent types -> |
424 // write non-safepoint dependent types -> |
417 // write checkpoint epoch transition list-> |
425 // write checkpoint epoch transition list-> |
418 // write stack trace checkpoint -> |
426 // write stack trace checkpoint -> |
419 // write string pool checkpoint -> |
427 // write string pool checkpoint -> |
420 // write storage -> |
428 // write object sample stacktraces -> |
421 // release stream lock |
429 // write storage -> |
|
430 // release stream lock |
422 // |
431 // |
423 void JfrRecorderService::pre_safepoint_write() { |
432 void JfrRecorderService::pre_safepoint_write() { |
424 MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
433 MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
425 assert(_chunkwriter.is_valid(), "invariant"); |
434 assert(_chunkwriter.is_valid(), "invariant"); |
426 _checkpoint_manager.write_types(); |
435 _checkpoint_manager.write_types(); |
427 _checkpoint_manager.write_epoch_transition_mspace(); |
436 _checkpoint_manager.write_epoch_transition_mspace(); |
428 write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false); |
437 write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false); |
429 write_stringpool_checkpoint(_string_pool, _chunkwriter); |
438 write_stringpool_checkpoint(_string_pool, _chunkwriter); |
|
439 if (LeakProfiler::is_running()) { |
|
440 // Exclusive access to the object sampler instance. |
|
441 // The sampler is released (unlocked) later in post_safepoint_write. |
|
442 ObjectSampler* const sampler = ObjectSampler::acquire(); |
|
443 assert(sampler != NULL, "invariant"); |
|
444 write_object_sample_stacktrace(sampler, _stack_trace_repository); |
|
445 } |
430 _storage.write(); |
446 _storage.write(); |
431 } |
447 } |
432 |
448 |
433 void JfrRecorderService::invoke_safepoint_write() { |
449 void JfrRecorderService::invoke_safepoint_write() { |
434 JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this); |
450 JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this); |
435 VMThread::execute(&safepoint_task); |
451 VMThread::execute(&safepoint_task); |
436 } |
452 } |
437 |
453 |
438 static void write_object_sample_stacktrace(JfrStackTraceRepository& stack_trace_repository) { |
|
439 WriteObjectSampleStacktrace object_sample_stacktrace(stack_trace_repository); |
|
440 object_sample_stacktrace.process(); |
|
441 } |
|
442 |
|
443 // |
454 // |
444 // safepoint write sequence |
455 // safepoint write sequence |
445 // |
456 // |
446 // lock stream lock -> |
457 // lock stream lock -> |
447 // write object sample stacktraces -> |
|
448 // write stacktrace repository -> |
458 // write stacktrace repository -> |
449 // write string pool -> |
459 // write string pool -> |
450 // write safepoint dependent types -> |
460 // write safepoint dependent types -> |
451 // write storage -> |
461 // write storage -> |
452 // shift_epoch -> |
462 // shift_epoch -> |
455 // release stream lock |
465 // release stream lock |
456 // |
466 // |
457 void JfrRecorderService::safepoint_write() { |
467 void JfrRecorderService::safepoint_write() { |
458 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
468 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
459 MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
469 MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
460 write_object_sample_stacktrace(_stack_trace_repository); |
|
461 write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true); |
470 write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true); |
462 write_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter); |
471 write_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter); |
463 _checkpoint_manager.write_safepoint_types(); |
472 _checkpoint_manager.write_safepoint_types(); |
464 _storage.write_at_safepoint(); |
473 _storage.write_at_safepoint(); |
465 _checkpoint_manager.shift_epoch(); |
474 _checkpoint_manager.shift_epoch(); |
475 } |
484 } |
476 |
485 |
477 // |
486 // |
478 // post-safepoint write sequence |
487 // post-safepoint write sequence |
479 // |
488 // |
480 // lock stream lock -> |
489 // write type set -> |
481 // write type set -> |
490 // release object sampler -> |
482 // write checkpoints -> |
491 // lock stream lock -> |
483 // write metadata event -> |
492 // write checkpoints -> |
484 // write chunk header -> |
493 // write metadata event -> |
485 // close chunk fd -> |
494 // write chunk header -> |
486 // release stream lock |
495 // close chunk fd -> |
|
496 // release stream lock |
487 // |
497 // |
488 void JfrRecorderService::post_safepoint_write() { |
498 void JfrRecorderService::post_safepoint_write() { |
489 assert(_chunkwriter.is_valid(), "invariant"); |
499 assert(_chunkwriter.is_valid(), "invariant"); |
490 // During the safepoint tasks just completed, the system transitioned to a new epoch. |
500 // During the safepoint tasks just completed, the system transitioned to a new epoch. |
491 // Type tagging is epoch relative which entails we are able to write out the |
501 // Type tagging is epoch relative which entails we are able to write out the |
492 // already tagged artifacts for the previous epoch. We can accomplish this concurrently |
502 // already tagged artifacts for the previous epoch. We can accomplish this concurrently |
493 // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint. |
503 // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint. |
494 _checkpoint_manager.write_type_set(); |
504 _checkpoint_manager.write_type_set(); |
495 MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
505 if (LeakProfiler::is_running()) { |
|
506 // The object sampler instance was exclusively acquired and locked in pre_safepoint_write. |
|
507 // Note: There is a dependency on write_type_set() above, ensure the release is subsequent. |
|
508 ObjectSampler::release(); |
|
509 } MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
496 // serialize any outstanding checkpoint memory |
510 // serialize any outstanding checkpoint memory |
497 _checkpoint_manager.write(); |
511 _checkpoint_manager.write(); |
498 // serialize the metadata descriptor event and close out the chunk |
512 // serialize the metadata descriptor event and close out the chunk |
499 _repository.close_chunk(write_metadata_event(_chunkwriter)); |
513 _repository.close_chunk(write_metadata_event(_chunkwriter)); |
500 assert(!_chunkwriter.is_valid(), "invariant"); |
514 assert(!_chunkwriter.is_valid(), "invariant"); |
509 } |
523 } |
510 |
524 |
511 void JfrRecorderService::finalize_current_chunk_on_vm_error() { |
525 void JfrRecorderService::finalize_current_chunk_on_vm_error() { |
512 assert(_chunkwriter.is_valid(), "invariant"); |
526 assert(_chunkwriter.is_valid(), "invariant"); |
513 pre_safepoint_write(); |
527 pre_safepoint_write(); |
514 JfrMetadataEvent::lock(); |
|
515 // Do not attempt safepoint dependent operations during emergency dump. |
528 // Do not attempt safepoint dependent operations during emergency dump. |
516 // Optimistically write tagged artifacts. |
529 // Optimistically write tagged artifacts. |
517 _checkpoint_manager.shift_epoch(); |
530 _checkpoint_manager.shift_epoch(); |
518 _checkpoint_manager.write_type_set(); |
|
519 // update time |
531 // update time |
520 _chunkwriter.time_stamp_chunk_now(); |
532 _chunkwriter.time_stamp_chunk_now(); |
521 post_safepoint_write(); |
533 post_safepoint_write(); |
522 assert(!_chunkwriter.is_valid(), "invariant"); |
534 assert(!_chunkwriter.is_valid(), "invariant"); |
523 } |
535 } |