< prev index next >

src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp

Print this page
*** 37,16 ***
  #include "jfr/recorder/service/jfrOptionSet.hpp"
  #include "jfr/recorder/storage/jfrEpochStorage.inline.hpp"
  #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
  #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp"
  #include "jfr/support/jfrKlassUnloading.hpp"
  #include "jfr/utilities/jfrBigEndian.hpp"
  #include "jfr/utilities/jfrIterator.hpp"
  #include "jfr/utilities/jfrLinkedList.inline.hpp"
  #include "jfr/utilities/jfrSignal.hpp"
  #include "jfr/utilities/jfrThreadIterator.hpp"
- #include "jfr/utilities/jfrTypes.hpp"
  #include "jfr/writers/jfrJavaEventWriter.hpp"
  #include "logging/log.hpp"
  #include "memory/iterator.hpp"
  #include "memory/resourceArea.hpp"
  #include "runtime/atomic.hpp"
--- 37,16 ---
  #include "jfr/recorder/service/jfrOptionSet.hpp"
  #include "jfr/recorder/storage/jfrEpochStorage.inline.hpp"
  #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
  #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp"
  #include "jfr/support/jfrKlassUnloading.hpp"
+ #include "jfr/support/jfrThreadLocal.hpp"
  #include "jfr/utilities/jfrBigEndian.hpp"
  #include "jfr/utilities/jfrIterator.hpp"
  #include "jfr/utilities/jfrLinkedList.inline.hpp"
  #include "jfr/utilities/jfrSignal.hpp"
  #include "jfr/utilities/jfrThreadIterator.hpp"
  #include "jfr/writers/jfrJavaEventWriter.hpp"
  #include "logging/log.hpp"
  #include "memory/iterator.hpp"
  #include "memory/resourceArea.hpp"
  #include "runtime/atomic.hpp"

*** 76,25 ***
    _instance = NULL;
  }
  
  JfrCheckpointManager::JfrCheckpointManager(JfrChunkWriter& cw) :
    _global_mspace(NULL),
!   _thread_local_mspace(NULL),
    _chunkwriter(cw) {}
  
  JfrCheckpointManager::~JfrCheckpointManager() {
    JfrTraceIdLoadBarrier::destroy();
    JfrTypeManager::destroy();
    delete _global_mspace;
!   delete _thread_local_mspace;
  }
  
  static const size_t global_buffer_prealloc_count = 2;
  static const size_t global_buffer_size = 512 * K;
  
! static const size_t thread_local_buffer_prealloc_count = 16;
! static const size_t thread_local_buffer_size = 128;
  
  bool JfrCheckpointManager::initialize() {
    assert(_global_mspace == NULL, "invariant");
    _global_mspace =  create_mspace<JfrCheckpointMspace, JfrCheckpointManager>(global_buffer_size, 0, 0, false, this); // post-pone preallocation
    if (_global_mspace == NULL) {
--- 76,25 ---
    _instance = NULL;
  }
  
  JfrCheckpointManager::JfrCheckpointManager(JfrChunkWriter& cw) :
    _global_mspace(NULL),
!   _java_thread_local_mspace(NULL),
    _chunkwriter(cw) {}
  
  JfrCheckpointManager::~JfrCheckpointManager() {
    JfrTraceIdLoadBarrier::destroy();
    JfrTypeManager::destroy();
    delete _global_mspace;
!   delete _java_thread_local_mspace;
  }
  
  static const size_t global_buffer_prealloc_count = 2;
  static const size_t global_buffer_size = 512 * K;
  
! static const size_t thread_local_buffer_prealloc_count = 32;
! static const size_t thread_local_buffer_size = 2 * K;
  
  bool JfrCheckpointManager::initialize() {
    assert(_global_mspace == NULL, "invariant");
    _global_mspace =  create_mspace<JfrCheckpointMspace, JfrCheckpointManager>(global_buffer_size, 0, 0, false, this); // post-pone preallocation
    if (_global_mspace == NULL) {

*** 105,15 ***
      Buffer* const buffer = mspace_allocate(global_buffer_size, _global_mspace);
      _global_mspace->add_to_live_list(buffer, i % 2 == 0);
    }
    assert(_global_mspace->free_list_is_empty(), "invariant");
  
!   assert(_thread_local_mspace == NULL, "invariant");
!   _thread_local_mspace = new JfrThreadLocalCheckpointMspace();
!   if (_thread_local_mspace == NULL || !_thread_local_mspace->initialize(thread_local_buffer_size,
!                                                                         JFR_MSPACE_UNLIMITED_CACHE_SIZE,
!                                                                         thread_local_buffer_prealloc_count)) {
      return false;
    }
    return JfrTypeManager::initialize() && JfrTraceIdLoadBarrier::initialize();
  }
  
--- 105,15 ---
      Buffer* const buffer = mspace_allocate(global_buffer_size, _global_mspace);
      _global_mspace->add_to_live_list(buffer, i % 2 == 0);
    }
    assert(_global_mspace->free_list_is_empty(), "invariant");
  
!   assert(_java_thread_local_mspace == NULL, "invariant");
!   _java_thread_local_mspace = new JfrThreadLocalCheckpointMspace();
!   if (_java_thread_local_mspace == NULL || !_java_thread_local_mspace->initialize(thread_local_buffer_size,
!                                                                                   JFR_MSPACE_UNLIMITED_CACHE_SIZE,
!                                                                                   thread_local_buffer_prealloc_count)) {
      return false;
    }
    return JfrTypeManager::initialize() && JfrTraceIdLoadBarrier::initialize();
  }
  

*** 160,11 ***
    return buffer;
  }
  
  const u1 thread_local_context = 1;
  
! static bool is_thread_local(JfrBuffer* buffer) {
    assert(buffer != NULL, "invariant");
    return buffer->context() == thread_local_context;
  }
  
  static void retire(JfrBuffer* buffer) {
--- 160,11 ---
    return buffer;
  }
  
  const u1 thread_local_context = 1;
  
! static bool is_thread_local(const JfrBuffer* buffer) {
    assert(buffer != NULL, "invariant");
    return buffer->context() == thread_local_context;
  }
  
  static void retire(JfrBuffer* buffer) {

*** 177,31 ***
   * The buffer is effectively invalidated for the thread post-return,
   * and the caller should take means to ensure that it is not referenced.
   */
  static void release(JfrBuffer* buffer) {
    DEBUG_ONLY(assert_release(buffer);)
!   if (is_thread_local(buffer)) {
-     retire(buffer);
-   } else {
      buffer->clear_lease();
      buffer->release();
    }
  }
  BufferPtr JfrCheckpointManager::acquire_thread_local(size_t size, Thread* thread) {
    assert(thread != NULL, "invariant");
!   JfrBuffer* const buffer = instance()._thread_local_mspace->acquire(size, thread);
    assert(buffer != NULL, "invariant");
    assert(buffer->free_size() >= size, "invariant");
    buffer->set_context(thread_local_context);
    assert(is_thread_local(buffer), "invariant");
    buffer->set_lease();
    return buffer;
  }
  
  BufferPtr JfrCheckpointManager::lease_thread_local(Thread* thread, size_t size /* 0 */) {
!   JfrBuffer* const buffer = acquire_thread_local(size, thread);
    DEBUG_ONLY(assert_lease(buffer);)
    return buffer;
  }
  
  BufferPtr JfrCheckpointManager::lease(BufferPtr old, Thread* thread, size_t size) {
    assert(old != NULL, "invariant");
--- 177,57 ---
   * The buffer is effectively invalidated for the thread post-return,
   * and the caller should take means to ensure that it is not referenced.
   */
  static void release(JfrBuffer* buffer) {
    DEBUG_ONLY(assert_release(buffer);)
!   if (!is_thread_local(buffer)) {
      buffer->clear_lease();
      buffer->release();
    }
  }
+ 
+ BufferPtr JfrCheckpointManager::get_thread_local(Thread* thread) {
+   assert(thread != NULL, "invariant");
+   assert(thread->is_Java_thread(), "invariant");
+   return JfrTraceIdEpoch::epoch() ? thread->jfr_thread_local()->_checkpoint_buffer_epoch_1 :
+                                     thread->jfr_thread_local()->_checkpoint_buffer_epoch_0;
+ }
+ 
+ void JfrCheckpointManager::set_thread_local(Thread* thread, BufferPtr buffer) {
+   assert(thread != NULL, "invariant");
+   assert(thread->is_Java_thread(), "invariant");
+   if (JfrTraceIdEpoch::epoch()) {
+     thread->jfr_thread_local()->_checkpoint_buffer_epoch_1 = buffer;
+   } else {
+     thread->jfr_thread_local()->_checkpoint_buffer_epoch_0 = buffer;
+   }
+ }
+ 
  BufferPtr JfrCheckpointManager::acquire_thread_local(size_t size, Thread* thread) {
    assert(thread != NULL, "invariant");
!   assert(thread->is_Java_thread(), "invariant");
+   JfrBuffer* const buffer = instance()._java_thread_local_mspace->acquire(size, thread);
    assert(buffer != NULL, "invariant");
    assert(buffer->free_size() >= size, "invariant");
    buffer->set_context(thread_local_context);
    assert(is_thread_local(buffer), "invariant");
    buffer->set_lease();
+   set_thread_local(thread, buffer);
    return buffer;
  }
  
  BufferPtr JfrCheckpointManager::lease_thread_local(Thread* thread, size_t size /* 0 */) {
!   JfrBuffer* buffer = get_thread_local(thread);
+   if (buffer == NULL) {
+     buffer = acquire_thread_local(size, thread);
+   } else if (buffer->free_size() < size) {
+     retire(buffer);
+     buffer = acquire_thread_local(size, thread);
+   }
    DEBUG_ONLY(assert_lease(buffer);)
+   assert(buffer->free_size() >= size, "invariant");
+   assert(get_thread_local(thread) == buffer, "invariant");
    return buffer;
  }
  
  BufferPtr JfrCheckpointManager::lease(BufferPtr old, Thread* thread, size_t size) {
    assert(old != NULL, "invariant");

*** 337,11 ***
  
  size_t JfrCheckpointManager::write() {
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current()));
    WriteOperation wo(_chunkwriter);
    MutexedWriteOperation mwo(wo);
!   _thread_local_mspace->iterate(mwo, true); // previous epoch list
    assert(_global_mspace->free_list_is_empty(), "invariant");
    ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true));
    WriteReleaseOperation wro(&mwo, &ro);
    process_live_list(wro, _global_mspace, true); // previous epoch list
    return wo.processed();
--- 363,11 ---
  
  size_t JfrCheckpointManager::write() {
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current()));
    WriteOperation wo(_chunkwriter);
    MutexedWriteOperation mwo(wo);
!   _java_thread_local_mspace->iterate(mwo, true); // previous epoch list
    assert(_global_mspace->free_list_is_empty(), "invariant");
    ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true));
    WriteReleaseOperation wro(&mwo, &ro);
    process_live_list(wro, _global_mspace, true); // previous epoch list
    return wo.processed();

*** 352,11 ***
  
  size_t JfrCheckpointManager::clear() {
    JfrTraceIdLoadBarrier::clear();
    clear_type_set();
    DiscardOperation discard_operation(mutexed); // mutexed discard mode
!   _thread_local_mspace->iterate(discard_operation, true); // previous epoch list
    ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true));
    DiscardReleaseOperation discard_op(&discard_operation, &ro);
    assert(_global_mspace->free_list_is_empty(), "invariant");
    process_live_list(discard_op, _global_mspace, true); // previous epoch list
    return discard_operation.elements();
--- 378,11 ---
  
  size_t JfrCheckpointManager::clear() {
    JfrTraceIdLoadBarrier::clear();
    clear_type_set();
    DiscardOperation discard_operation(mutexed); // mutexed discard mode
!   _java_thread_local_mspace->iterate(discard_operation, true); // previous epoch list
    ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true));
    DiscardReleaseOperation discard_op(&discard_operation, &ro);
    assert(_global_mspace->free_list_is_empty(), "invariant");
    process_live_list(discard_op, _global_mspace, true); // previous epoch list
    return discard_operation.elements();

*** 456,23 ***
      }
    }
    if (_new_checkpoint.is_signaled_with_reset()) {
      WriteOperation wo(_chunkwriter);
      MutexedWriteOperation mwo(wo);
!     _thread_local_mspace->iterate(mwo); // current epoch list
      assert(_global_mspace->live_list_is_nonempty(), "invariant");
      process_live_list(mwo, _global_mspace); // current epoch list
    }
    return elements;
  }
  
! void JfrCheckpointManager::create_thread_blob(Thread* thread) {
!   JfrTypeManager::create_thread_blob(thread);
  }
  
! void JfrCheckpointManager::write_thread_checkpoint(Thread* thread) {
!   JfrTypeManager::write_thread_checkpoint(thread);
  }
  
  class JfrNotifyClosure : public ThreadClosure {
   public:
    void do_thread(Thread* thread) {
--- 482,26 ---
      }
    }
    if (_new_checkpoint.is_signaled_with_reset()) {
      WriteOperation wo(_chunkwriter);
      MutexedWriteOperation mwo(wo);
!     _java_thread_local_mspace->iterate(mwo); // current epoch list
      assert(_global_mspace->live_list_is_nonempty(), "invariant");
      process_live_list(mwo, _global_mspace); // current epoch list
    }
    return elements;
  }
  
! JfrBlobHandle JfrCheckpointManager::create_thread_blob(JavaThread* jt, traceid tid, oop vthread) {
!   assert(jt != NULL, "invariant");
+   assert(Thread::current() == jt, "invariant");
+   DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
+   return JfrTypeManager::create_thread_blob(jt, tid, vthread);
  }
  
! void JfrCheckpointManager::write_checkpoint(Thread* thread, traceid tid, oop vthread) {
!   JfrTypeManager::write_checkpoint(thread, tid, vthread);
  }
  
  class JfrNotifyClosure : public ThreadClosure {
   public:
    void do_thread(Thread* thread) {
< prev index next >