src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
branchJEP-349-branch
changeset 57882 562f598d303c
parent 57873 68134337dbf8
child 57886 87f8a814310d
equal deleted inserted replaced
57878:bffba8d6611a 57882:562f598d303c
   179     return lease_free(size, manager._epoch_transition_mspace, lease_retry, thread);
   179     return lease_free(size, manager._epoch_transition_mspace, lease_retry, thread);
   180   }
   180   }
   181   return lease_free(size, manager._free_list_mspace, lease_retry, thread);
   181   return lease_free(size, manager._free_list_mspace, lease_retry, thread);
   182 }
   182 }
   183 
   183 
       
   184 JfrCheckpointMspace* JfrCheckpointManager::lookup(BufferPtr old) const {
       
   185   assert(old != NULL, "invariant");
       
   186   return _free_list_mspace->in_free_list(old) ? _free_list_mspace : _epoch_transition_mspace;
       
   187 }
       
   188 
       
   189 BufferPtr JfrCheckpointManager::lease_buffer(BufferPtr old, Thread* thread, size_t size /* 0 */) {
       
   190   assert(old != NULL, "invariant");
       
   191   JfrCheckpointMspace* mspace = instance().lookup(old);
       
   192   assert(mspace != NULL, "invariant");
       
   193   return lease_free(size, mspace, lease_retry, thread);
       
   194 }
       
   195 
   184 /*
   196 /*
   185 * If the buffer was a "lease" from the free list, release back.
   197 * If the buffer was a "lease", release back.
   186 *
   198 *
   187 * The buffer is effectively invalidated for the thread post-return,
   199 * The buffer is effectively invalidated for the thread post-return,
   188 * and the caller should take means to ensure that it is not referenced.
   200 * and the caller should take means to ensure that it is not referenced.
   189 */
   201 */
   190 static void release(BufferPtr const buffer, Thread* thread) {
   202 static void release(BufferPtr const buffer, Thread* thread) {
   200     // indicates a lease is being returned
   212     // indicates a lease is being returned
   201     release(old, thread);
   213     release(old, thread);
   202     return NULL;
   214     return NULL;
   203   }
   215   }
   204   // migration of in-flight information
   216   // migration of in-flight information
   205   BufferPtr const new_buffer = lease_buffer(thread, used + requested);
   217   BufferPtr const new_buffer = lease_buffer(old, thread, used + requested);
   206   if (new_buffer != NULL) {
   218   if (new_buffer != NULL) {
   207     migrate_outstanding_writes(old, new_buffer, used, requested);
   219     migrate_outstanding_writes(old, new_buffer, used, requested);
   208   }
   220   }
   209   release(old, thread);
   221   release(old, thread);
   210   return new_buffer; // might be NULL
   222   return new_buffer; // might be NULL
   211 }
   223 }
   212 
   224 
   213 // offsets into the JfrCheckpointEntry
   225 // offsets into the JfrCheckpointEntry
   214 static const juint starttime_offset = sizeof(jlong);
   226 static const juint starttime_offset = sizeof(jlong);
   215 static const juint duration_offset = starttime_offset + sizeof(jlong);
   227 static const juint duration_offset = starttime_offset + sizeof(jlong);
   216 static const juint flushpoint_offset = duration_offset + sizeof(jlong);
   228 static const juint mode_offset = duration_offset + sizeof(jlong);
   217 static const juint types_offset = flushpoint_offset + sizeof(juint);
   229 static const juint types_offset = mode_offset + sizeof(juint);
   218 static const juint payload_offset = types_offset + sizeof(juint);
   230 static const juint payload_offset = types_offset + sizeof(juint);
   219 
   231 
   220 template <typename Return>
   232 template <typename Return>
   221 static Return read_data(const u1* data) {
   233 static Return read_data(const u1* data) {
   222   return JfrBigEndian::read<Return>(data);
   234   return JfrBigEndian::read<Return>(data);
   232 
   244 
   233 static jlong duration(const u1* data) {
   245 static jlong duration(const u1* data) {
   234   return read_data<jlong>(data + duration_offset);
   246   return read_data<jlong>(data + duration_offset);
   235 }
   247 }
   236 
   248 
       
   249 static u1 mode(const u1* data) {
       
   250   return read_data<u1>(data + mode_offset);
       
   251 }
       
   252 
   237 static juint number_of_types(const u1* data) {
   253 static juint number_of_types(const u1* data) {
   238   return read_data<juint>(data + types_offset);
   254   return read_data<juint>(data + types_offset);
   239 }
   255 }
   240 
   256 
   241 static void write_checkpoint_header(JfrChunkWriter& cw, int64_t offset_prev_cp_event, const u1* data) {
   257 static void write_checkpoint_header(JfrChunkWriter& cw, int64_t offset_prev_cp_event, const u1* data) {
   242   cw.reserve(sizeof(u4));
   258   cw.reserve(sizeof(u4));
   243   cw.write<u8>(EVENT_CHECKPOINT);
   259   cw.write<u8>(EVENT_CHECKPOINT);
   244   cw.write<u8>(starttime(data));
   260   cw.write(starttime(data));
   245   cw.write<u8>(duration(data));
   261   cw.write(duration(data));
   246   cw.write<u8>(offset_prev_cp_event);
   262   cw.write(offset_prev_cp_event);
   247   cw.write<bool>(false); // not a flushpoint
   263   cw.write(mode(data));
   248   cw.write<juint>(number_of_types(data));
   264   cw.write(number_of_types(data));
   249 }
   265 }
   250 
   266 
   251 static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) {
   267 static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) {
   252   assert(data != NULL, "invariant");
   268   assert(data != NULL, "invariant");
   253   cw.write_unbuffered(data + payload_offset, size - sizeof(JfrCheckpointEntry));
   269   cw.write_unbuffered(data + payload_offset, size - sizeof(JfrCheckpointEntry));
   348   assert(_free_list_mspace->is_full_empty(), "invariant");
   364   assert(_free_list_mspace->is_full_empty(), "invariant");
   349   process_free_list(fo, _free_list_mspace);
   365   process_free_list(fo, _free_list_mspace);
   350   return wo.processed();
   366   return wo.processed();
   351 }
   367 }
   352 
   368 
       
   369 // Optimization for write_types() and write_threads() is to write
       
   370 // directly into the epoch transition mspace because we will immediately
       
   371 // serialize and reset this mspace post-write.
       
   372 static JfrBuffer* get_epoch_transition_buffer(JfrCheckpointMspace* mspace, Thread* t) {
       
   373   assert(mspace != NULL, "invariant");
       
   374   JfrBuffer* const buffer = mspace->free_head();
       
   375   assert(buffer != NULL, "invariant");
       
   376   buffer->acquire(t);
       
   377   buffer->set_lease();
       
   378   DEBUG_ONLY(assert_free_lease(buffer);)
       
   379   return buffer;
       
   380 }
       
   381 
   353 size_t JfrCheckpointManager::write_types() {
   382 size_t JfrCheckpointManager::write_types() {
   354   ResourceMark rm;
   383   ResourceMark rm;
   355   HandleMark hm;
   384   HandleMark hm;
   356   Thread* const t = Thread::current();
   385   Thread* const t = Thread::current();
   357   // Optimization here is to write the types directly into the epoch transition mspace
   386   JfrCheckpointWriter writer(t, get_epoch_transition_buffer(_epoch_transition_mspace, t), STATICS);
   358   // because the caller will immediately serialize and reset this mspace.
       
   359   JfrBuffer* const buffer = _epoch_transition_mspace->free_tail();
       
   360   assert(buffer != NULL, "invariant");
       
   361   buffer->acquire(t);
       
   362   buffer->set_lease();
       
   363   DEBUG_ONLY(assert_free_lease(buffer);)
       
   364   JfrCheckpointWriter writer(t, buffer);
       
   365   JfrTypeManager::write_types(writer);
   387   JfrTypeManager::write_types(writer);
   366   return writer.used_size();
   388   return writer.used_size();
   367 }
   389 }
   368 
   390 
       
   391 size_t JfrCheckpointManager::write_threads() {
       
   392   ResourceMark rm;
       
   393   HandleMark hm;
       
   394   Thread* const t = Thread::current();
       
   395   JfrCheckpointWriter writer(t, get_epoch_transition_buffer(_epoch_transition_mspace, t), THREADS);
       
   396   JfrTypeManager::write_threads(writer);
       
   397   return writer.used_size();
       
   398 }
       
   399 
   369 size_t JfrCheckpointManager::write_epoch_transition_mspace() {
   400 size_t JfrCheckpointManager::write_epoch_transition_mspace() {
   370   return write_mspace<ExclusiveOp, CompositeOperation>(_epoch_transition_mspace, _chunkwriter);
   401   return write_mspace<ExclusiveOp, CompositeOperation>(_epoch_transition_mspace, _chunkwriter);
   371 }
   402 }
   372 
   403 
   373 size_t JfrCheckpointManager::write_constants() {
   404 size_t JfrCheckpointManager::write_constants() {
   374   write_types();
   405   write_types();
       
   406   write_threads();
   375   return write_epoch_transition_mspace();
   407   return write_epoch_transition_mspace();
   376 }
   408 }
   377 
   409 
   378 class JfrNotifyClosure : public ThreadClosure {
   410 class JfrNotifyClosure : public ThreadClosure {
   379  public:
   411  public: