src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
branchJEP-349-branch
changeset 57360 5d043a159d5c
parent 54623 1126f0607c70
child 57870 00860d9caf4d
equal deleted inserted replaced
57359:4cab5edc2950 57360:5d043a159d5c
    21  * questions.
    21  * questions.
    22  *
    22  *
    23  */
    23  */
    24 
    24 
    25 #include "precompiled.hpp"
    25 #include "precompiled.hpp"
       
    26 #include "jfrfiles/jfrEventClasses.hpp"
    26 #include "jfr/jni/jfrJavaSupport.hpp"
    27 #include "jfr/jni/jfrJavaSupport.hpp"
    27 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
    28 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
    28 #include "jfr/recorder/jfrRecorder.hpp"
    29 #include "jfr/recorder/jfrRecorder.hpp"
    29 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
    30 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
    30 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
    31 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
    73 
    74 
    74 static void* rotation_thread = NULL;
    75 static void* rotation_thread = NULL;
    75 static const int rotation_try_limit = 1000;
    76 static const int rotation_try_limit = 1000;
    76 static const int rotation_retry_sleep_millis = 10;
    77 static const int rotation_retry_sleep_millis = 10;
    77 
    78 
       
    79 // incremented on each flushpoint
       
    80 static u8 flushpoint_id = 0;
       
    81 
    78 class RotationLock : public StackObj {
    82 class RotationLock : public StackObj {
    79  private:
    83  private:
    80   Thread* const _thread;
    84   Thread* const _thread;
    81   bool _acquired;
    85   bool _acquired;
    82 
    86 
   128     }
   132     }
   129   }
   133   }
   130   bool not_acquired() const { return !_acquired; }
   134   bool not_acquired() const { return !_acquired; }
   131 };
   135 };
   132 
   136 
       
   137 template <typename E, typename Instance, size_t(Instance::*func)()>
       
   138 class ServiceFunctor {
       
   139  private:
       
   140   Instance& _instance;
       
   141   u4 _elements;
       
   142  public:
       
   143   typedef E EventType;
       
   144   ServiceFunctor(Instance& instance) : _instance(instance), _elements(0) {}
       
   145   bool process() {
       
   146     _elements = (u4)(_instance.*func)();
       
   147     return true;
       
   148   }
       
   149   u4 elements() const { return _elements; }
       
   150 };
       
   151 
       
   152 template <typename ContentFunctor>
       
   153 class WriteSubsystem : public StackObj {
       
   154  protected:
       
   155   const JfrTicks _start_time;
       
   156   JfrTicks _end_time;
       
   157   JfrChunkWriter& _cw;
       
   158   ContentFunctor& _content_functor;
       
   159   const int64_t _start_offset;
       
   160  public:
       
   161   typedef typename ContentFunctor::EventType EventType;
       
   162 
       
   163   WriteSubsystem(JfrChunkWriter& cw, ContentFunctor& functor) :
       
   164     _start_time(JfrTicks::now()),
       
   165     _end_time(),
       
   166     _cw(cw),
       
   167     _content_functor(functor),
       
   168     _start_offset(_cw.current_offset()) {
       
   169     assert(_cw.is_valid(), "invariant");
       
   170   }
       
   171 
       
   172   bool process() {
       
   173     // invocation
       
   174     _content_functor.process();
       
   175     _end_time = JfrTicks::now();
       
   176     return 0 != _content_functor.elements();
       
   177   }
       
   178 
       
   179   const JfrTicks& start_time() const {
       
   180     return _start_time;
       
   181   }
       
   182 
       
   183   const JfrTicks& end_time() const {
       
   184     return _end_time;
       
   185   }
       
   186 
       
   187   int64_t start_offset() const {
       
   188     return _start_offset;
       
   189   }
       
   190 
       
   191   int64_t end_offset() const {
       
   192     return current_offset();
       
   193   }
       
   194 
       
   195   int64_t current_offset() const {
       
   196     return _cw.current_offset();
       
   197   }
       
   198 
       
   199   u4 elements() const {
       
   200     return (u4) _content_functor.elements();
       
   201   }
       
   202 
       
   203   u4 size() const {
       
   204     return (u4)(end_offset() - start_offset());
       
   205   }
       
   206 
       
   207   static bool is_event_enabled() {
       
   208     return EventType::is_enabled();
       
   209   }
       
   210 
       
   211   static u8 event_id() {
       
   212     return EventType::eventId;
       
   213   }
       
   214 
       
   215   void write_elements(int64_t offset) {
       
   216     _cw.write_padded_at_offset<u4>(elements(), offset);
       
   217   }
       
   218 
       
   219   void write_size() {
       
   220     _cw.write_padded_at_offset<u4>(size(), start_offset());
       
   221   }
       
   222 
       
   223   void set_last_checkpoint() {
       
   224     _cw.set_last_checkpoint_offset(start_offset());
       
   225   }
       
   226 
       
   227   void rewind() {
       
   228     _cw.seek(start_offset());
       
   229   }
       
   230 
       
   231 };
       
   232 
   133 static int64_t write_checkpoint_event_prologue(JfrChunkWriter& cw, u8 type_id) {
   233 static int64_t write_checkpoint_event_prologue(JfrChunkWriter& cw, u8 type_id) {
   134   const int64_t prev_cp_offset = cw.previous_checkpoint_offset();
   234   const int64_t last_cp_offset = cw.last_checkpoint_offset();
   135   const int64_t prev_cp_relative_offset = 0 == prev_cp_offset ? 0 : prev_cp_offset - cw.current_offset();
   235   const int64_t last_cp_relative_offset = 0 == last_cp_offset ? 0 : last_cp_offset - cw.current_offset();
   136   cw.reserve(sizeof(u4));
   236   cw.reserve(sizeof(u4));
   137   cw.write<u8>(EVENT_CHECKPOINT);
   237   cw.write<u8>(EVENT_CHECKPOINT);
   138   cw.write(JfrTicks::now());
   238   cw.write(JfrTicks::now());
   139   cw.write((int64_t)0);
   239   cw.write<int64_t>((int64_t)0);
   140   cw.write(prev_cp_relative_offset); // write previous checkpoint offset delta
   240   cw.write(last_cp_relative_offset); // write last checkpoint offset delta
   141   cw.write<bool>(false); // flushpoint
   241   cw.write<bool>(false); // flushpoint
   142   cw.write((u4)1); // nof types in this checkpoint
   242   cw.write<u4>((u4)1); // nof types in this checkpoint
   143   cw.write(type_id);
   243   cw.write<u8>(type_id);
   144   const int64_t number_of_elements_offset = cw.current_offset();
   244   const int64_t number_of_elements_offset = cw.current_offset();
   145   cw.reserve(sizeof(u4));
   245   cw.reserve(sizeof(u4));
   146   return number_of_elements_offset;
   246   return number_of_elements_offset;
   147 }
   247 }
   148 
   248 
   149 template <typename ContentFunctor>
   249 template <typename ContentFunctor>
   150 class WriteCheckpointEvent : public StackObj {
   250 class WriteSubsystemCheckpointEvent : public WriteSubsystem<ContentFunctor> {
   151  private:
   251  private:
   152   JfrChunkWriter& _cw;
   252   const u8 _type_id;
   153   u8 _type_id;
       
   154   ContentFunctor& _content_functor;
       
   155  public:
   253  public:
   156   WriteCheckpointEvent(JfrChunkWriter& cw, u8 type_id, ContentFunctor& functor) :
   254   WriteSubsystemCheckpointEvent(JfrChunkWriter& cw, ContentFunctor& functor, u8 type_id) :
   157     _cw(cw),
   255     WriteSubsystem<ContentFunctor>(cw, functor), _type_id(type_id) {}
   158     _type_id(type_id),
   256 
   159     _content_functor(functor) {
       
   160     assert(_cw.is_valid(), "invariant");
       
   161   }
       
   162   bool process() {
   257   bool process() {
   163     // current_cp_offset is also offset for the event size header field
   258     const int64_t num_elements_offset = write_checkpoint_event_prologue(this->_cw, _type_id);
   164     const int64_t current_cp_offset = _cw.current_offset();
   259     if (!WriteSubsystem<ContentFunctor>::process()) {
   165     const int64_t num_elements_offset = write_checkpoint_event_prologue(_cw, _type_id);
       
   166     // invocation
       
   167     _content_functor.process();
       
   168     const u4 number_of_elements = (u4)_content_functor.processed();
       
   169     if (number_of_elements == 0) {
       
   170       // nothing to do, rewind writer to start
   260       // nothing to do, rewind writer to start
   171       _cw.seek(current_cp_offset);
   261       this->rewind();
   172       return true;
   262       assert(this->current_offset() == this->start_offset(), "invariant");
       
   263       return false;
   173     }
   264     }
   174     assert(number_of_elements > 0, "invariant");
   265     assert(this->elements() > 0, "invariant");
   175     assert(_cw.current_offset() > num_elements_offset, "invariant");
   266     assert(this->current_offset() > num_elements_offset, "invariant");
   176     _cw.write_padded_at_offset<u4>(number_of_elements, num_elements_offset);
   267     this->write_elements(num_elements_offset);
   177     _cw.write_padded_at_offset<u4>((u4)_cw.current_offset() - current_cp_offset, current_cp_offset);
   268     this->write_size();
   178     // update writer with last checkpoint position
   269     this->set_last_checkpoint();
   179     _cw.set_previous_checkpoint_offset(current_cp_offset);
       
   180     return true;
   270     return true;
   181   }
   271   }
   182 };
   272 };
   183 
   273 
   184 template <typename Instance, size_t(Instance::*func)()>
   274 template <typename Functor>
   185 class ServiceFunctor {
   275 static void write_flush_event(Functor& f) {
   186  private:
   276   if (!Functor::is_event_enabled()) {
   187   Instance& _instance;
   277     return;
   188   size_t _processed;
   278   }
   189  public:
   279   typename Functor::EventType e(UNTIMED);
   190   ServiceFunctor(Instance& instance) : _instance(instance), _processed(0) {}
   280   e.set_starttime(f.start_time());
   191   bool process() {
   281   e.set_endtime(f.end_time());
   192     _processed = (_instance.*func)();
   282   e.set_flushId(flushpoint_id);
   193     return true;
   283   e.set_elements(f.elements());
   194   }
   284   e.set_size(f.size());
   195   size_t processed() const { return _processed; }
   285   e.commit();
   196 };
   286 }
       
   287 
       
   288 template <typename Functor>
       
   289 static u4 invoke(Functor& f) {
       
   290   f.process();
       
   291   return f.elements();
       
   292 }
       
   293 
       
   294 template <typename Functor>
       
   295 static u4 invoke_with_flush_event(Functor& f) {
       
   296   const u4 elements = invoke(f);
       
   297   if (elements != 0) {
       
   298     write_flush_event(f);
       
   299   }
       
   300   return elements;
       
   301 }
   197 
   302 
   198 template <typename Instance, void(Instance::*func)()>
   303 template <typename Instance, void(Instance::*func)()>
   199 class JfrVMOperation : public VM_Operation {
   304 class JfrVMOperation : public VM_Operation {
   200  private:
   305  private:
   201   Instance& _instance;
   306   Instance& _instance;
   204   void doit() { (_instance.*func)(); }
   309   void doit() { (_instance.*func)(); }
   205   VMOp_Type type() const { return VMOp_JFRCheckpoint; }
   310   VMOp_Type type() const { return VMOp_JFRCheckpoint; }
   206   Mode evaluation_mode() const { return _safepoint; } // default
   311   Mode evaluation_mode() const { return _safepoint; } // default
   207 };
   312 };
   208 
   313 
   209 class WriteStackTraceRepository : public StackObj {
   314 class FlushStackTraceRepository : public StackObj {
   210  private:
   315  private:
   211   JfrStackTraceRepository& _repo;
   316   JfrStackTraceRepository& _repo;
   212   JfrChunkWriter& _cw;
   317   JfrChunkWriter& _cw;
   213   size_t _elements_processed;
   318   size_t _elements;
   214   bool _clear;
   319   bool _clear;
   215 
   320 
   216  public:
   321  public:
   217   WriteStackTraceRepository(JfrStackTraceRepository& repo, JfrChunkWriter& cw, bool clear) :
   322   typedef EventFlushStacktrace EventType;
   218     _repo(repo), _cw(cw), _elements_processed(0), _clear(clear) {}
   323   FlushStackTraceRepository(JfrStackTraceRepository& repo, JfrChunkWriter& cw, bool clear) :
       
   324     _repo(repo), _cw(cw), _elements(0), _clear(clear) {}
   219   bool process() {
   325   bool process() {
   220     _elements_processed = _repo.write(_cw, _clear);
   326     _elements = _repo.write(_cw, _clear);
   221     return true;
   327     return true;
   222   }
   328   }
   223   size_t processed() const { return _elements_processed; }
   329   size_t elements() const { return _elements; }
   224   void reset() { _elements_processed = 0; }
   330   void reset() { _elements = 0; }
       
   331 };
       
   332 
       
   333 class FlushMetadataEvent : public StackObj {
       
   334  private:
       
   335   JfrChunkWriter& _cw;
       
   336  public:
       
   337   typedef EventFlushMetadata EventType;
       
   338   FlushMetadataEvent(JfrChunkWriter& cw) : _cw(cw) {}
       
   339   bool process() {
       
   340     JfrMetadataEvent::write(_cw);
       
   341     return true;
       
   342   }
       
   343   size_t elements() const { return 1; }
   225 };
   344 };
   226 
   345 
   227 static bool recording = false;
   346 static bool recording = false;
   228 
   347 
   229 static void set_recording_state(bool is_recording) {
   348 static void set_recording_state(bool is_recording) {
   316     prepare_for_vm_error_rotation();
   435     prepare_for_vm_error_rotation();
   317   }
   436   }
   318   if (msgs & (MSGBIT(MSG_STOP))) {
   437   if (msgs & (MSGBIT(MSG_STOP))) {
   319     stop();
   438     stop();
   320   }
   439   }
   321   // action determined by chunkwriter state
   440   if (!_storage.control().to_disk()) {
   322   if (!_chunkwriter.is_valid()) {
       
   323     in_memory_rotation();
   441     in_memory_rotation();
   324     return;
   442     return;
   325   }
   443   }
   326   if (vm_error) {
   444   if (vm_error) {
   327     vm_error_rotation();
   445     vm_error_rotation();
   336   }
   454   }
   337   _checkpoint_manager.register_service_thread(Thread::current());
   455   _checkpoint_manager.register_service_thread(Thread::current());
   338 }
   456 }
   339 
   457 
   340 void JfrRecorderService::open_new_chunk(bool vm_error) {
   458 void JfrRecorderService::open_new_chunk(bool vm_error) {
   341   assert(!_chunkwriter.is_valid(), "invariant");
       
   342   assert(!JfrStream_lock->owned_by_self(), "invariant");
       
   343   JfrChunkRotation::on_rotation();
   459   JfrChunkRotation::on_rotation();
   344   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   460   const bool valid_chunk = _repository.open_chunk(vm_error);
   345   if (!_repository.open_chunk(vm_error)) {
   461   _storage.control().set_to_disk(valid_chunk);
   346     assert(!_chunkwriter.is_valid(), "invariant");
   462   if (valid_chunk) {
   347     _storage.control().set_to_disk(false);
   463     _checkpoint_manager.write_constants();
   348     return;
   464   }
   349   }
       
   350   assert(_chunkwriter.is_valid(), "invariant");
       
   351   _storage.control().set_to_disk(true);
       
   352 }
   465 }
   353 
   466 
   354 void JfrRecorderService::in_memory_rotation() {
   467 void JfrRecorderService::in_memory_rotation() {
   355   assert(!_chunkwriter.is_valid(), "invariant");
       
   356   // currently running an in-memory recording
   468   // currently running an in-memory recording
       
   469   assert(!_storage.control().to_disk(), "invariant");
   357   open_new_chunk();
   470   open_new_chunk();
   358   if (_chunkwriter.is_valid()) {
   471   if (_chunkwriter.is_valid()) {
   359     // dump all in-memory buffer data to the newly created chunk
   472     // dump all in-memory buffer data to the newly created chunk
   360     serialize_storage_from_in_memory_recording();
   473     serialize_storage_from_in_memory_recording();
   361   }
   474   }
   362 }
   475 }
   363 
   476 
   364 void JfrRecorderService::serialize_storage_from_in_memory_recording() {
   477 void JfrRecorderService::serialize_storage_from_in_memory_recording() {
   365   assert(!JfrStream_lock->owned_by_self(), "not holding stream lock!");
       
   366   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
       
   367   _storage.write();
   478   _storage.write();
   368 }
   479 }
   369 
   480 
   370 void JfrRecorderService::chunk_rotation() {
   481 void JfrRecorderService::chunk_rotation() {
   371   finalize_current_chunk();
   482   finalize_current_chunk();
   373 }
   484 }
   374 
   485 
   375 void JfrRecorderService::finalize_current_chunk() {
   486 void JfrRecorderService::finalize_current_chunk() {
   376   assert(_chunkwriter.is_valid(), "invariant");
   487   assert(_chunkwriter.is_valid(), "invariant");
   377   write();
   488   write();
   378   assert(!_chunkwriter.is_valid(), "invariant");
       
   379 }
   489 }
   380 
   490 
   381 void JfrRecorderService::write() {
   491 void JfrRecorderService::write() {
   382   ResourceMark rm;
   492   ResourceMark rm;
   383   HandleMark hm;
   493   HandleMark hm;
   384   pre_safepoint_write();
   494   pre_safepoint_write();
   385   invoke_safepoint_write();
   495   invoke_safepoint_write();
   386   post_safepoint_write();
   496   post_safepoint_write();
   387 }
   497 }
   388 
   498 
   389 typedef ServiceFunctor<JfrStringPool, &JfrStringPool::write> WriteStringPool;
   499 typedef ServiceFunctor<EventFlushStringPool, JfrStringPool, &JfrStringPool::write> FlushStringPoolFunctor;
   390 typedef ServiceFunctor<JfrStringPool, &JfrStringPool::write_at_safepoint> WriteStringPoolSafepoint;
   500 typedef ServiceFunctor<EventFlushStringPool, JfrStringPool, &JfrStringPool::write_at_safepoint> FlushStringPoolSafepointFunctor;
   391 typedef WriteCheckpointEvent<WriteStackTraceRepository> WriteStackTraceCheckpoint;
   501 typedef WriteSubsystemCheckpointEvent<FlushStackTraceRepository> FlushStackTraceCheckpoint;
   392 typedef WriteCheckpointEvent<WriteStringPool> WriteStringPoolCheckpoint;
   502 typedef WriteSubsystemCheckpointEvent<FlushStringPoolFunctor> FlushStringPoolCheckpoint;
   393 typedef WriteCheckpointEvent<WriteStringPoolSafepoint> WriteStringPoolCheckpointSafepoint;
   503 typedef WriteSubsystemCheckpointEvent<FlushStringPoolSafepointFunctor> FlushStringPoolCheckpointSafepoint;
   394 
   504 
   395 static void write_stacktrace_checkpoint(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter, bool clear) {
   505 static u4 flush_stacktrace(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter, bool clear) {
   396   WriteStackTraceRepository write_stacktrace_repo(stack_trace_repo, chunkwriter, clear);
   506   FlushStackTraceRepository flush_stacktrace_repo(stack_trace_repo, chunkwriter, clear);
   397   WriteStackTraceCheckpoint write_stack_trace_checkpoint(chunkwriter, TYPE_STACKTRACE, write_stacktrace_repo);
   507   FlushStackTraceCheckpoint flush_stack_trace_checkpoint(chunkwriter, flush_stacktrace_repo, TYPE_STACKTRACE);
   398   write_stack_trace_checkpoint.process();
   508   return invoke_with_flush_event(flush_stack_trace_checkpoint);
   399 }
   509 }
   400 
   510 
   401 static void write_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
   511 static u4 flush_stacktrace(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter) {
   402   WriteStringPool write_string_pool(string_pool);
   512   return flush_stacktrace(stack_trace_repo, chunkwriter, false);
   403   WriteStringPoolCheckpoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool);
   513 }
   404   write_string_pool_checkpoint.process();
   514 
   405 }
   515 static u4 flush_stacktrace_checkpoint(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter, bool clear) {
   406 
   516   FlushStackTraceRepository flush_stacktrace_repo(stack_trace_repo, chunkwriter, clear);
   407 static void write_stringpool_checkpoint_safepoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
   517   FlushStackTraceCheckpoint flush_stack_trace_checkpoint(chunkwriter, flush_stacktrace_repo, TYPE_STACKTRACE);
   408   WriteStringPoolSafepoint write_string_pool(string_pool);
   518   return invoke(flush_stack_trace_checkpoint);
   409   WriteStringPoolCheckpointSafepoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool);
   519 }
   410   write_string_pool_checkpoint.process();
   520 
       
   521 static u4 flush_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
       
   522   FlushStringPoolFunctor flush_string_pool(string_pool);
       
   523   FlushStringPoolCheckpoint flush_string_pool_checkpoint(chunkwriter, flush_string_pool, TYPE_STRING);
       
   524   return invoke_with_flush_event(flush_string_pool_checkpoint);
       
   525 }
       
   526 
       
   527 static u4 flush_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
       
   528   FlushStringPoolFunctor flush_string_pool(string_pool);
       
   529   FlushStringPoolCheckpoint flush_string_pool_checkpoint(chunkwriter, flush_string_pool, TYPE_STRING);
       
   530   return invoke(flush_string_pool_checkpoint);
       
   531 }
       
   532 
       
   533 static u4 flush_stringpool_checkpoint_safepoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
       
   534   FlushStringPoolSafepointFunctor flush_string_pool(string_pool);
       
   535   FlushStringPoolCheckpointSafepoint flush_string_pool_checkpoint(chunkwriter, flush_string_pool, TYPE_STRING);
       
   536   return invoke(flush_string_pool_checkpoint);
       
   537 }
       
   538 
       
   539 typedef ServiceFunctor<EventFlushTypeSet, JfrCheckpointManager, &JfrCheckpointManager::flush_type_set> FlushTypeSetFunctor;
       
   540 typedef WriteSubsystem<FlushTypeSetFunctor> FlushTypeSet;
       
   541 
       
   542 static u4 flush_typeset(JfrCheckpointManager& checkpoint_manager, JfrChunkWriter& chunkwriter) {
       
   543   FlushTypeSetFunctor flush_type_set(checkpoint_manager);
       
   544   FlushTypeSet fts(chunkwriter, flush_type_set);
       
   545   return invoke_with_flush_event(fts);
       
   546 }
       
   547 
       
   548 typedef WriteSubsystem<FlushMetadataEvent> FlushMetadata;
       
   549 
       
   550 static u4 flush_metadata_event(JfrChunkWriter& chunkwriter) {
       
   551   assert(chunkwriter.is_valid(), "invariant");
       
   552   FlushMetadataEvent fme(chunkwriter);
       
   553   FlushMetadata fm(chunkwriter, fme);
       
   554   return invoke_with_flush_event(fm);
       
   555 }
       
   556 
       
   557 static u4 flush_metadata_event_checkpoint(JfrChunkWriter& chunkwriter) {
       
   558   assert(chunkwriter.is_valid(), "invariant");
       
   559   FlushMetadataEvent wme(chunkwriter);
       
   560   FlushMetadata wm(chunkwriter, wme);
       
   561   return invoke(wm);
       
   562 }
       
   563 
       
   564 static JfrBuffer* thread_local_buffer() {
       
   565   return Thread::current()->jfr_thread_local()->native_buffer();
       
   566 }
       
   567 
       
   568 static void reset_buffer(JfrBuffer* buffer) {
       
   569   assert(buffer != NULL, "invariant");
       
   570   assert(buffer == thread_local_buffer(), "invariant");
       
   571   buffer->set_pos(const_cast<u1*>(buffer->top()));
       
   572   assert(buffer->empty(), "invariant");
       
   573 }
       
   574 
       
   575 static void reset_thread_local_buffer() {
       
   576   reset_buffer(thread_local_buffer());
       
   577 }
       
   578 
       
   579 static void write_thread_local_buffer(JfrChunkWriter& chunkwriter) {
       
   580   JfrBuffer * const buffer = thread_local_buffer();
       
   581   assert(buffer != NULL, "invariant");
       
   582   if (!buffer->empty()) {
       
   583     chunkwriter.write_unbuffered(buffer->top(), buffer->pos() - buffer->top());
       
   584     reset_buffer(buffer);
       
   585   }
       
   586   assert(buffer->empty(), "invariant");
       
   587 }
       
   588 
       
   589 typedef ServiceFunctor<EventFlushStorage, JfrStorage, &JfrStorage::write> FlushStorageFunctor;
       
   590 typedef WriteSubsystem<FlushStorageFunctor> FlushStorage;
       
   591 
       
   592 static size_t flush_storage(JfrStorage& storage, JfrChunkWriter& chunkwriter) {
       
   593   assert(chunkwriter.is_valid(), "invariant");
       
   594   FlushStorageFunctor fsf(storage);
       
   595   FlushStorage fs(chunkwriter, fsf);
       
   596   return invoke_with_flush_event(fs);
       
   597 }
       
   598 
       
   599 typedef ServiceFunctor<EventFlush, JfrRecorderService, &JfrRecorderService::flush> FlushFunctor;
       
   600 typedef WriteSubsystem<FlushFunctor> Flush;
       
   601 
       
   602 static bool write_metadata_in_flushpoint = false;
       
   603 
       
   604 size_t JfrRecorderService::flush() {
       
   605   size_t total_elements = 0;
       
   606   if (write_metadata_in_flushpoint) {
       
   607     total_elements = flush_metadata_event(_chunkwriter);
       
   608   }
       
   609   const size_t storage_elements = flush_storage(_storage, _chunkwriter);
       
   610   if (0 == storage_elements) {
       
   611     return total_elements;
       
   612   }
       
   613   total_elements += storage_elements;
       
   614   total_elements += flush_stacktrace(_stack_trace_repository, _chunkwriter);
       
   615   if (_string_pool.modified()) {
       
   616     total_elements += flush_stringpool(_string_pool, _chunkwriter);
       
   617   }
       
   618   total_elements += flush_typeset(_checkpoint_manager, _chunkwriter);
       
   619   return total_elements;
       
   620 }
       
   621 
       
   622 void JfrRecorderService::flush(int msgs) {
       
   623   assert(_chunkwriter.is_valid(), "invariant");
       
   624   ResourceMark rm;
       
   625   HandleMark hm;
       
   626   reset_thread_local_buffer();
       
   627   ++flushpoint_id;
       
   628   write_metadata_in_flushpoint = (msgs & MSGBIT(MSG_FLUSHPOINT_METADATA));
       
   629   FlushFunctor flushpoint(*this);
       
   630   Flush fl(_chunkwriter, flushpoint);
       
   631   invoke_with_flush_event(fl);
       
   632   write_thread_local_buffer(_chunkwriter);
       
   633   _repository.flush_chunk();
   411 }
   634 }
   412 
   635 
   413 //
   636 //
   414 // pre-safepoint write sequence
   637 // pre-safepoint write sequence
   415 //
   638 //
   416 //  lock stream lock ->
   639 //  write checkpoint epoch transition list->
   417 //    write non-safepoint dependent types ->
   640 //    write stack trace checkpoint ->
   418 //      write checkpoint epoch transition list->
   641 //      write string pool checkpoint ->
   419 //        write stack trace checkpoint ->
   642 //        notify about pending rotation ->
   420 //          write string pool checkpoint ->
   643 //          write storage
   421 //            write storage ->
       
   422 //              release stream lock
       
   423 //
   644 //
   424 void JfrRecorderService::pre_safepoint_write() {
   645 void JfrRecorderService::pre_safepoint_write() {
   425   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
       
   426   assert(_chunkwriter.is_valid(), "invariant");
   646   assert(_chunkwriter.is_valid(), "invariant");
   427   _checkpoint_manager.write_types();
       
   428   _checkpoint_manager.write_epoch_transition_mspace();
   647   _checkpoint_manager.write_epoch_transition_mspace();
   429   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false);
   648   flush_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false);
   430   write_stringpool_checkpoint(_string_pool, _chunkwriter);
   649   if (_string_pool.modified()) {
       
   650     flush_stringpool_checkpoint(_string_pool, _chunkwriter);
       
   651   }
       
   652   _checkpoint_manager.notify_types_on_rotation();
   431   _storage.write();
   653   _storage.write();
   432 }
   654 }
   433 
   655 
   434 void JfrRecorderService::invoke_safepoint_write() {
   656 void JfrRecorderService::invoke_safepoint_write() {
   435   JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this);
   657   JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this);
   442 }
   664 }
   443 
   665 
   444 //
   666 //
   445 // safepoint write sequence
   667 // safepoint write sequence
   446 //
   668 //
   447 //   lock stream lock ->
   669 // write object sample stacktraces ->
   448 //     write object sample stacktraces ->
   670 //   write stacktrace repository ->
   449 //       write stacktrace repository ->
   671 //     write string pool ->
   450 //         write string pool ->
   672 //       write storage ->
   451 //           write safepoint dependent types ->
   673 //         notify java threads ->
   452 //             write storage ->
   674 //           shift_epoch ->
   453 //                 shift_epoch ->
   675 //             update time
   454 //                   update time ->
       
   455 //                     lock metadata descriptor ->
       
   456 //                       release stream lock
       
   457 //
   676 //
   458 void JfrRecorderService::safepoint_write() {
   677 void JfrRecorderService::safepoint_write() {
   459   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   678   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   460   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
       
   461   write_object_sample_stacktrace(_stack_trace_repository);
   679   write_object_sample_stacktrace(_stack_trace_repository);
   462   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true);
   680   flush_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true);
   463   write_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter);
   681   if (_string_pool.modified()) {
   464   _checkpoint_manager.write_safepoint_types();
   682     flush_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter);
       
   683   }
   465   _storage.write_at_safepoint();
   684   _storage.write_at_safepoint();
       
   685   _checkpoint_manager.notify_threads();
   466   _checkpoint_manager.shift_epoch();
   686   _checkpoint_manager.shift_epoch();
   467   _chunkwriter.time_stamp_chunk_now();
   687   _chunkwriter.time_stamp_chunk_now();
   468   JfrMetadataEvent::lock();
       
   469 }
       
   470 
       
   471 static int64_t write_metadata_event(JfrChunkWriter& chunkwriter) {
       
   472   assert(chunkwriter.is_valid(), "invariant");
       
   473   const int64_t metadata_offset = chunkwriter.current_offset();
       
   474   JfrMetadataEvent::write(chunkwriter, metadata_offset);
       
   475   return metadata_offset;
       
   476 }
   688 }
   477 
   689 
   478 //
   690 //
   479 // post-safepoint write sequence
   691 // post-safepoint write sequence
   480 //
   692 //
   481 //  lock stream lock ->
   693 //  write type set ->
   482 //    write type set ->
   694 //    write checkpoints ->
   483 //      write checkpoints ->
   695 //      write metadata event ->
   484 //        write metadata event ->
   696 //        close chunk
   485 //          write chunk header ->
       
   486 //            close chunk fd ->
       
   487 //              release stream lock
       
   488 //
   697 //
   489 void JfrRecorderService::post_safepoint_write() {
   698 void JfrRecorderService::post_safepoint_write() {
   490   assert(_chunkwriter.is_valid(), "invariant");
   699   assert(_chunkwriter.is_valid(), "invariant");
   491   // During the safepoint tasks just completed, the system transitioned to a new epoch.
   700   // During the safepoint tasks just completed, the system transitioned to a new epoch.
   492   // Type tagging is epoch relative which entails we are able to write out the
   701   // Type tagging is epoch relative which entails we are able to write out the
   493   // already tagged artifacts for the previous epoch. We can accomplish this concurrently
   702   // already tagged artifacts for the previous epoch. We can accomplish this concurrently
   494   // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint.
   703   // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint.
   495   _checkpoint_manager.write_type_set();
   704   _checkpoint_manager.write_type_set();
   496   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
       
   497   // serialize any outstanding checkpoint memory
   705   // serialize any outstanding checkpoint memory
   498   _checkpoint_manager.write();
   706   _checkpoint_manager.write();
   499   // serialize the metadata descriptor event and close out the chunk
   707   // serialize the metadata descriptor event and close out the chunk
   500   _repository.close_chunk(write_metadata_event(_chunkwriter));
   708   flush_metadata_event_checkpoint(_chunkwriter);
   501   assert(!_chunkwriter.is_valid(), "invariant");
   709   _repository.close_chunk();
   502 }
   710 }
   503 
   711 
   504 void JfrRecorderService::vm_error_rotation() {
   712 void JfrRecorderService::vm_error_rotation() {
   505   if (_chunkwriter.is_valid()) {
   713   if (_chunkwriter.is_valid()) {
   506     finalize_current_chunk_on_vm_error();
   714     finalize_current_chunk_on_vm_error();
   510 }
   718 }
   511 
   719 
   512 void JfrRecorderService::finalize_current_chunk_on_vm_error() {
   720 void JfrRecorderService::finalize_current_chunk_on_vm_error() {
   513   assert(_chunkwriter.is_valid(), "invariant");
   721   assert(_chunkwriter.is_valid(), "invariant");
   514   pre_safepoint_write();
   722   pre_safepoint_write();
   515   JfrMetadataEvent::lock();
       
   516   // Do not attempt safepoint dependent operations during emergency dump.
   723   // Do not attempt safepoint dependent operations during emergency dump.
   517   // Optimistically write tagged artifacts.
   724   // Optimistically write tagged artifacts.
   518   _checkpoint_manager.shift_epoch();
   725   _checkpoint_manager.shift_epoch();
   519   _checkpoint_manager.write_type_set();
   726   _checkpoint_manager.write_type_set();
   520   // update time
   727   // update time
   521   _chunkwriter.time_stamp_chunk_now();
   728   _chunkwriter.time_stamp_chunk_now();
   522   post_safepoint_write();
   729   post_safepoint_write();
   523   assert(!_chunkwriter.is_valid(), "invariant");
       
   524 }
   730 }
   525 
   731 
   526 void JfrRecorderService::process_full_buffers() {
   732 void JfrRecorderService::process_full_buffers() {
   527   if (_chunkwriter.is_valid()) {
   733   if (_chunkwriter.is_valid()) {
   528     assert(!JfrStream_lock->owned_by_self(), "invariant");
       
   529     MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
       
   530     _storage.write_full();
   734     _storage.write_full();
   531   }
   735   }
   532 }
   736 }
   533 
   737 
   534 void JfrRecorderService::scavenge() {
   738 void JfrRecorderService::scavenge() {