--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp Thu Oct 17 20:53:35 2019 +0100
@@ -37,6 +37,7 @@
#include "jfr/utilities/jfrTypes.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
+#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/os.inline.hpp"
@@ -87,22 +88,18 @@
static const size_t checkpoint_buffer_cache_count = 2;
static const size_t checkpoint_buffer_size = 512 * K;
-static JfrCheckpointMspace* create_mspace(size_t buffer_size, size_t limit, size_t cache_count, JfrCheckpointManager* system) {
- JfrCheckpointMspace* mspace = new JfrCheckpointMspace(buffer_size, limit, cache_count, system);
- if (mspace != NULL) {
- mspace->initialize();
- }
- return mspace;
+static JfrCheckpointMspace* allocate_mspace(size_t size, size_t limit, size_t cache_count, JfrCheckpointManager* mgr) {
+ return create_mspace<JfrCheckpointMspace, JfrCheckpointManager>(size, limit, cache_count, mgr);
}
bool JfrCheckpointManager::initialize() {
assert(_free_list_mspace == NULL, "invariant");
- _free_list_mspace = create_mspace(checkpoint_buffer_size, unlimited_mspace_size, checkpoint_buffer_cache_count, this);
+ _free_list_mspace = allocate_mspace(checkpoint_buffer_size, unlimited_mspace_size, checkpoint_buffer_cache_count, this);
if (_free_list_mspace == NULL) {
return false;
}
assert(_epoch_transition_mspace == NULL, "invariant");
- _epoch_transition_mspace = create_mspace(checkpoint_buffer_size, unlimited_mspace_size, checkpoint_buffer_cache_count, this);
+ _epoch_transition_mspace = allocate_mspace(checkpoint_buffer_size, unlimited_mspace_size, checkpoint_buffer_cache_count, this);
if (_epoch_transition_mspace == NULL) {
return false;
}
@@ -114,22 +111,6 @@
return JfrTypeManager::initialize();
}
-bool JfrCheckpointManager::use_epoch_transition_mspace(const Thread* thread) const {
- return _service_thread != thread && OrderAccess::load_acquire(&_checkpoint_epoch_state) != JfrTraceIdEpoch::epoch();
-}
-
-void JfrCheckpointManager::synchronize_epoch() {
- assert(_checkpoint_epoch_state != JfrTraceIdEpoch::epoch(), "invariant");
- OrderAccess::storestore();
- _checkpoint_epoch_state = JfrTraceIdEpoch::epoch();
-}
-
-void JfrCheckpointManager::shift_epoch() {
- debug_only(const u1 current_epoch = JfrTraceIdEpoch::current();)
- JfrTraceIdEpoch::shift_epoch();
- assert(current_epoch != JfrTraceIdEpoch::current(), "invariant");
-}
-
void JfrCheckpointManager::register_service_thread(const Thread* thread) {
_service_thread = thread;
}
@@ -151,7 +132,6 @@
}
#ifdef ASSERT
-
bool JfrCheckpointManager::is_locked() const {
return _lock->owned_by_self();
}
@@ -167,7 +147,6 @@
assert(buffer->lease(), "invariant");
assert(buffer->acquired_by_self(), "invariant");
}
-
#endif // ASSERT
static BufferPtr lease_free(size_t size, JfrCheckpointMspace* mspace, size_t retry_count, Thread* thread) {
@@ -185,6 +164,10 @@
return buffer;
}
+bool JfrCheckpointManager::use_epoch_transition_mspace(const Thread* thread) const {
+ return _service_thread != thread && OrderAccess::load_acquire(&_checkpoint_epoch_state) != JfrTraceIdEpoch::epoch();
+}
+
static const size_t lease_retry = 10;
BufferPtr JfrCheckpointManager::lease_buffer(Thread* thread, size_t size /* 0 */) {
@@ -256,33 +239,33 @@
return read_data<juint>(data + types_offset);
}
-static void write_checkpoint_header(JfrChunkWriter& cw, intptr_t offset_prev_cp_event, const u1* data) {
+static void write_checkpoint_header(JfrChunkWriter& cw, int64_t offset_prev_cp_event, const u1* data) {
cw.reserve(sizeof(u4));
- cw.write((u8)EVENT_CHECKPOINT);
+ cw.write<u8>(EVENT_CHECKPOINT);
cw.write(starttime(data));
cw.write(duration(data));
- cw.write((jlong)offset_prev_cp_event);
+ cw.write(offset_prev_cp_event);
cw.write(is_flushpoint(data));
cw.write(number_of_types(data));
}
static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) {
assert(data != NULL, "invariant");
- cw.write_unbuffered(data + payload_offset, size);
+ cw.write_unbuffered(data + payload_offset, size - sizeof(JfrCheckpointEntry));
}
static size_t write_checkpoint_event(JfrChunkWriter& cw, const u1* data) {
assert(data != NULL, "invariant");
- const intptr_t previous_checkpoint_event = cw.previous_checkpoint_offset();
- const intptr_t event_begin = cw.current_offset();
- const intptr_t offset_to_previous_checkpoint_event = 0 == previous_checkpoint_event ? 0 : previous_checkpoint_event - event_begin;
- const jlong total_checkpoint_size = total_size(data);
- write_checkpoint_header(cw, offset_to_previous_checkpoint_event, data);
- write_checkpoint_content(cw, data, total_checkpoint_size - sizeof(JfrCheckpointEntry));
- const jlong checkpoint_event_size = cw.current_offset() - event_begin;
- cw.write_padded_at_offset<u4>(checkpoint_event_size, event_begin);
- cw.set_previous_checkpoint_offset(event_begin);
- return (size_t)total_checkpoint_size;
+ const int64_t event_begin = cw.current_offset();
+ const int64_t last_checkpoint_event = cw.last_checkpoint_offset();
+ const int64_t delta = last_checkpoint_event == 0 ? 0 : last_checkpoint_event - event_begin;
+ const int64_t checkpoint_size = total_size(data);
+ write_checkpoint_header(cw, delta, data);
+ write_checkpoint_content(cw, data, checkpoint_size);
+ const int64_t event_size = cw.current_offset() - event_begin;
+ cw.write_padded_at_offset<u4>(event_size, event_begin);
+ cw.set_last_checkpoint_offset(event_begin);
+ return (size_t)checkpoint_size;
}
static size_t write_checkpoints(JfrChunkWriter& cw, const u1* data, size_t size) {
@@ -290,14 +273,14 @@
assert(data != NULL, "invariant");
assert(size > 0, "invariant");
const u1* const limit = data + size;
- const u1* next_entry = data;
+ const u1* next = data;
size_t processed = 0;
- while (next_entry < limit) {
- const size_t checkpoint_size = write_checkpoint_event(cw, next_entry);
+ while (next < limit) {
+ const size_t checkpoint_size = write_checkpoint_event(cw, next);
processed += checkpoint_size;
- next_entry += checkpoint_size;
+ next += checkpoint_size;
}
- assert(next_entry == limit, "invariant");
+ assert(next == limit, "invariant");
return processed;
}
@@ -317,29 +300,34 @@
};
typedef CheckpointWriteOp<JfrCheckpointMspace::Type> WriteOperation;
-typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
typedef ReleaseOp<JfrCheckpointMspace> CheckpointReleaseOperation;
-typedef CompositeOperation<MutexedWriteOperation, CheckpointReleaseOperation> CheckpointWriteOperation;
-static size_t write_mspace_exclusive(JfrCheckpointMspace* mspace, JfrChunkWriter& chunkwriter) {
- Thread* const thread = Thread::current();
+template <template <typename> class WriterHost, template <typename, typename> class CompositeOperation>
+static size_t write_mspace(JfrCheckpointMspace* mspace, JfrChunkWriter& chunkwriter) {
+ assert(mspace != NULL, "invariant");
WriteOperation wo(chunkwriter);
- MutexedWriteOperation mwo(wo);
- CheckpointReleaseOperation cro(mspace, thread, false);
- CheckpointWriteOperation cpwo(&mwo, &cro);
+ WriterHost<WriteOperation> wh(wo);
+ CheckpointReleaseOperation cro(mspace, Thread::current(), false);
+ CompositeOperation<WriterHost<WriteOperation>, CheckpointReleaseOperation> co(&wh, &cro);
assert(mspace->is_full_empty(), "invariant");
- process_free_list(cpwo, mspace);
+ process_free_list(co, mspace);
return wo.processed();
}
+void JfrCheckpointManager::synchronize_epoch() {
+ assert(_checkpoint_epoch_state != JfrTraceIdEpoch::epoch(), "invariant");
+ OrderAccess::storestore();
+ _checkpoint_epoch_state = JfrTraceIdEpoch::epoch();
+}
+
size_t JfrCheckpointManager::write() {
- const size_t processed = write_mspace_exclusive(_free_list_mspace, _chunkwriter);
+ const size_t processed = write_mspace<MutexedWriteOp, CompositeOperation>(_free_list_mspace, _chunkwriter);
synchronize_epoch();
return processed;
}
size_t JfrCheckpointManager::write_epoch_transition_mspace() {
- return write_mspace_exclusive(_epoch_transition_mspace, _chunkwriter);
+ return write_mspace<ExclusiveOp, CompositeOperation>(_epoch_transition_mspace, _chunkwriter);
}
typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation;
@@ -373,10 +361,16 @@
JfrTypeManager::write_type_set_for_unloaded_classes();
}
-void JfrCheckpointManager::create_thread_checkpoint(JavaThread* jt) {
- JfrTypeManager::create_thread_checkpoint(jt);
+void JfrCheckpointManager::create_thread_blob(JavaThread* jt) {
+ JfrTypeManager::create_thread_blob(jt);
}
void JfrCheckpointManager::write_thread_checkpoint(JavaThread* jt) {
JfrTypeManager::write_thread_checkpoint(jt);
}
+
+void JfrCheckpointManager::shift_epoch() {
+ debug_only(const u1 current_epoch = JfrTraceIdEpoch::current();)
+ JfrTraceIdEpoch::shift_epoch();
+ assert(current_epoch != JfrTraceIdEpoch::current(), "invariant");
+}