diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index db55f289c4c..d2402ccbcd0 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -338,18 +338,20 @@ static size_t write_storage(JfrStorage& storage, JfrChunkWriter& chunkwriter) { return invoke(fs); } -typedef Content StringPool; -typedef WriteCheckpointEvent WriteStringPool; +typedef Content FlushStringPoolFunctor; +typedef Content WriteStringPoolFunctor; +typedef WriteCheckpointEvent FlushStringPool; +typedef WriteCheckpointEvent WriteStringPool; static u4 flush_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) { - StringPool sp(string_pool); - WriteStringPool wsp(chunkwriter, sp, TYPE_STRING); - return invoke(wsp); + FlushStringPoolFunctor fspf(string_pool); + FlushStringPool fsp(chunkwriter, fspf, TYPE_STRING); + return invoke(fsp); } static u4 write_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) { - StringPool sp(string_pool); - WriteStringPool wsp(chunkwriter, sp, TYPE_STRING); + WriteStringPoolFunctor wspf(string_pool); + WriteStringPool wsp(chunkwriter, wspf, TYPE_STRING); return invoke(wsp); } @@ -461,7 +463,6 @@ void JfrRecorderService::clear() { void JfrRecorderService::pre_safepoint_clear() { clear_object_allocation_sampling(); - _string_pool.clear(); _storage.clear(); JfrStackTraceRepository::clear(); } @@ -475,7 +476,6 @@ void JfrRecorderService::invoke_safepoint_clear() { void JfrRecorderService::safepoint_clear() { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); _checkpoint_manager.begin_epoch_shift(); - _string_pool.clear(); _storage.clear(); _chunkwriter.set_time_stamp(); JfrStackTraceRepository::clear(); @@ -483,6 +483,7 @@ void JfrRecorderService::safepoint_clear() { } void JfrRecorderService::post_safepoint_clear() { + _string_pool.clear(); _checkpoint_manager.clear(); } @@ -567,9 +568,6 @@ void JfrRecorderService::pre_safepoint_write() { // The sampler is released (unlocked) later in post_safepoint_write. ObjectSampleCheckpoint::on_rotation(ObjectSampler::acquire()); } - if (_string_pool.is_modified()) { - write_stringpool(_string_pool, _chunkwriter); - } write_storage(_storage, _chunkwriter); if (_stack_trace_repository.is_modified()) { write_stacktrace(_stack_trace_repository, _chunkwriter, false); @@ -587,9 +585,6 @@ void JfrRecorderService::safepoint_write() { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); _checkpoint_manager.begin_epoch_shift(); JfrStackTraceRepository::clear_leak_profiler(); - if (_string_pool.is_modified()) { - write_stringpool(_string_pool, _chunkwriter); - } _checkpoint_manager.on_rotation(); _storage.write_at_safepoint(); _chunkwriter.set_time_stamp(); @@ -603,6 +598,7 @@ void JfrRecorderService::post_safepoint_write() { // Type tagging is epoch relative which entails we are able to write out the // already tagged artifacts for the previous epoch. We can accomplish this concurrently // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint. + write_stringpool(_string_pool, _chunkwriter); _checkpoint_manager.write_type_set(); if (LeakProfiler::is_running()) { // The object sampler instance was exclusively acquired and locked in pre_safepoint_write. diff --git a/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.hpp b/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.hpp index a7ba65698cb..fdfd32d1f90 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.hpp @@ -208,4 +208,11 @@ class EpochDispatchOp { size_t elements() const { return _elements; } }; +template +class ReinitializationOp { + public: + typedef T Type; + bool process(Type* t); +}; + #endif // SHARE_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_HPP diff --git a/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp b/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp index 620d830afef..a80c16d2e14 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp @@ -175,4 +175,13 @@ size_t EpochDispatchOp::dispatch(bool previous_epoch, const u1* eleme return elements; } +template +bool ReinitializationOp::process(T* t) { + assert(t != nullptr, "invariant"); + assert(t->identity() != nullptr, "invariant"); + t->reinitialize(); + t->release(); + return true; +} + #endif // SHARE_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_INLINE_HPP diff --git a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp index 715f996c748..cc099cdb92e 100644 --- a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp +++ b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp @@ -77,10 +77,17 @@ static const size_t string_pool_buffer_size = 512 * K; bool JfrStringPool::initialize() { assert(_mspace == nullptr, "invariant"); _mspace = create_mspace(string_pool_buffer_size, - string_pool_cache_count, // cache limit - string_pool_cache_count, // cache preallocate count - false, // preallocate_to_free_list (== preallocate directly to live list) + 0, + 0, // cache preallocate count + false, this); + + // preallocate buffer count to each of the epoch live lists + for (size_t i = 0; i < string_pool_cache_count * 2; ++i) { + Buffer* const buffer = mspace_allocate(string_pool_buffer_size, _mspace); + _mspace->add_to_live_list(buffer, i % 2 == 0); + } + assert(_mspace->free_list_is_empty(), "invariant"); return _mspace != nullptr; } @@ -95,11 +102,7 @@ static void release(BufferPtr buffer, Thread* thread) { assert(buffer->lease(), "invariant"); assert(buffer->acquired_by_self(), "invariant"); buffer->clear_lease(); - if (buffer->transient()) { - buffer->set_retired(); - } else { - buffer->release(); - } + buffer->release(); } BufferPtr JfrStringPool::flush(BufferPtr old, size_t used, size_t requested, Thread* thread) { @@ -180,8 +183,10 @@ typedef StringPoolOp WriteOperation; typedef StringPoolOp DiscardOperation; typedef ExclusiveOp ExclusiveWriteOperation; typedef ExclusiveOp ExclusiveDiscardOperation; +typedef ReinitializationOp ReinitializationOperation; typedef ReleaseWithExcisionOp ReleaseOperation; typedef CompositeOperation WriteReleaseOperation; +typedef CompositeOperation WriteReinitializeOperation; typedef CompositeOperation DiscardReleaseOperation; size_t JfrStringPool::write() { @@ -189,10 +194,22 @@ size_t JfrStringPool::write() { WriteOperation wo(_chunkwriter, thread); ExclusiveWriteOperation ewo(wo); assert(_mspace->free_list_is_empty(), "invariant"); - ReleaseOperation ro(_mspace, _mspace->live_list()); + ReleaseOperation ro(_mspace, _mspace->live_list(true)); // previous epoch list WriteReleaseOperation wro(&ewo, &ro); assert(_mspace->live_list_is_nonempty(), "invariant"); - process_live_list(wro, _mspace); + process_live_list(wro, _mspace, true); // previous epoch list + return wo.processed(); +} + +size_t JfrStringPool::flush() { + Thread* const thread = Thread::current(); + WriteOperation wo(_chunkwriter, thread); + ExclusiveWriteOperation ewo(wo); + ReinitializationOperation rio; + WriteReinitializeOperation wro(&ewo, &rio); + assert(_mspace->free_list_is_empty(), "invariant"); + assert(_mspace->live_list_is_nonempty(), "invariant"); + process_live_list(wro, _mspace); // current epoch list return wo.processed(); } @@ -200,10 +217,10 @@ size_t JfrStringPool::clear() { DiscardOperation discard_operation; ExclusiveDiscardOperation edo(discard_operation); assert(_mspace->free_list_is_empty(), "invariant"); - ReleaseOperation ro(_mspace, _mspace->live_list()); + ReleaseOperation ro(_mspace, _mspace->live_list(true)); // previous epoch list DiscardReleaseOperation discard_op(&edo, &ro); assert(_mspace->live_list_is_nonempty(), "invariant"); - process_live_list(discard_op, _mspace); + process_live_list(discard_op, _mspace, true); // previous epoch list return discard_operation.processed(); } diff --git a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.hpp b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.hpp index cbe5f5744a9..c4ff2af6c5c 100644 --- a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.hpp +++ b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ class JavaThread; class JfrChunkWriter; class JfrStringPool; -typedef JfrMemorySpace > JfrStringPoolMspace; +typedef JfrMemorySpace, JfrLinkedList, true > JfrStringPoolMspace; // // Although called JfrStringPool, a more succinct description would be @@ -45,8 +45,10 @@ typedef JfrMemorySpace