8205053: Decouple type registration from framework lifecycle

Reviewed-by: mgronlun, pliden, stefank
This commit is contained in:
Erik Gahlin 2018-06-21 20:52:52 +02:00
parent 9773083b55
commit 76d0843d18
5 changed files with 142 additions and 177 deletions

View File

@ -66,7 +66,6 @@ JfrCheckpointManager::JfrCheckpointManager(JfrChunkWriter& cw) :
_free_list_mspace(NULL),
_epoch_transition_mspace(NULL),
_lock(NULL),
_type_manager(NULL),
_service_thread(NULL),
_chunkwriter(cw),
_checkpoint_epoch_state(JfrTraceIdEpoch::epoch()) {}
@ -81,9 +80,7 @@ JfrCheckpointManager::~JfrCheckpointManager() {
if (_lock != NULL) {
delete _lock;
}
if (_type_manager) {
delete _type_manager;
}
JfrTypeManager::clear();
}
static const size_t unlimited_mspace_size = 0;
@ -109,14 +106,12 @@ bool JfrCheckpointManager::initialize() {
if (_epoch_transition_mspace == NULL) {
return false;
}
assert(_type_manager == NULL, "invariant");
_type_manager = new JfrTypeManager();
if (_type_manager == NULL || !_type_manager->initialize()) {
return false;
}
assert(_lock == NULL, "invariant");
_lock = new Mutex(Monitor::leaf - 1, "Checkpoint mutex", Mutex::_allow_vm_block_flag, Monitor::_safepoint_check_never);
return _lock != NULL;
if (_lock == NULL) {
return false;
}
return JfrTypeManager::initialize();
}
bool JfrCheckpointManager::use_epoch_transition_mspace(const Thread* thread) const {
@ -354,37 +349,32 @@ size_t JfrCheckpointManager::clear() {
return discarder.processed();
}
bool JfrCheckpointManager::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* cs) {
assert(cs != NULL, "invariant");
return instance()._type_manager->register_serializer(id, require_safepoint, permit_cache, cs);
}
size_t JfrCheckpointManager::write_types() {
JfrCheckpointWriter writer(false, true, Thread::current());
_type_manager->write_types(writer);
JfrTypeManager::write_types(writer);
return writer.used_size();
}
size_t JfrCheckpointManager::write_safepoint_types() {
// this is also a "flushpoint"
JfrCheckpointWriter writer(true, true, Thread::current());
_type_manager->write_safepoint_types(writer);
JfrTypeManager::write_safepoint_types(writer);
return writer.used_size();
}
void JfrCheckpointManager::write_type_set() {
_type_manager->write_type_set();
JfrTypeManager::write_type_set();
}
void JfrCheckpointManager::write_type_set_for_unloaded_classes() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
instance()._type_manager->write_type_set_for_unloaded_classes();
JfrTypeManager::write_type_set_for_unloaded_classes();
}
void JfrCheckpointManager::create_thread_checkpoint(JavaThread* jt) {
instance()._type_manager->create_thread_checkpoint(jt);
JfrTypeManager::create_thread_checkpoint(jt);
}
void JfrCheckpointManager::write_thread_checkpoint(JavaThread* jt) {
instance()._type_manager->write_thread_checkpoint(jt);
JfrTypeManager::write_thread_checkpoint(jt);
}

View File

@ -28,7 +28,6 @@
#include "jfr/recorder/storage/jfrBuffer.hpp"
#include "jfr/recorder/storage/jfrMemorySpace.hpp"
#include "jfr/recorder/storage/jfrMemorySpaceRetrieval.hpp"
#include "jfr/utilities/jfrTypes.hpp"
class JfrCheckpointManager;
class JfrChunkWriter;
@ -59,7 +58,6 @@ class JfrCheckpointManager : public JfrCHeapObj {
JfrCheckpointMspace* _free_list_mspace;
JfrCheckpointMspace* _epoch_transition_mspace;
Mutex* _lock;
JfrTypeManager* _type_manager;
const Thread* _service_thread;
JfrChunkWriter& _chunkwriter;
bool _checkpoint_epoch_state;
@ -91,8 +89,6 @@ class JfrCheckpointManager : public JfrCHeapObj {
bool initialize();
static void destroy();
static bool register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer);
public:
void register_service_thread(const Thread* t);
static void write_type_set_for_unloaded_classes();

View File

@ -63,12 +63,6 @@
#include "gc/z/zStat.hpp"
#endif
// implementation for the static registration function exposed in the api
bool JfrSerializer::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* cs) {
assert(cs != NULL, "invariant");
return JfrCheckpointManager::register_serializer(id, require_safepoint, permit_cache, cs);
}
class JfrCheckpointThreadCountClosure : public ThreadClosure {
private:
u4 _total_threads;
@ -357,8 +351,6 @@ void ZStatisticsCounterTypeConstant::serialize(JfrCheckpointWriter& writer) {
writer.write_key(counter->id());
writer.write(counter->name());
}
#else
writer.write_count(0);
#endif
}
@ -369,7 +361,5 @@ void ZStatisticsSamplerTypeConstant::serialize(JfrCheckpointWriter& writer) {
writer.write_key(sampler->id());
writer.write(sampler->name());
}
#else
writer.write_count(0);
#endif
}

View File

@ -23,107 +23,131 @@
*/
#include "precompiled.hpp"
#include "jfr/metadata/jfrSerializer.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
#include "jfr/recorder/checkpoint/types/jfrType.hpp"
#include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp"
#include "jfr/utilities/jfrDoublyLinkedList.hpp"
#include "jfr/utilities/jfrIterator.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/exceptions.hpp"
#include "runtime/semaphore.hpp"
JfrSerializerRegistration::JfrSerializerRegistration(JfrTypeId id, bool permit_cache, JfrSerializer* cs) :
_next(NULL),
_prev(NULL),
_serializer(cs),
_cache(),
_id(id),
_permit_cache(permit_cache) {}
class JfrSerializerRegistration : public JfrCHeapObj {
private:
JfrSerializerRegistration* _next;
JfrSerializerRegistration* _prev;
JfrSerializer* _serializer;
mutable JfrCheckpointBlobHandle _cache;
JfrTypeId _id;
bool _permit_cache;
JfrSerializerRegistration::~JfrSerializerRegistration() {
delete _serializer;
}
public:
JfrSerializerRegistration(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) :
_next(NULL), _prev(NULL), _serializer(serializer), _cache(), _id(id), _permit_cache(permit_cache) {}
JfrSerializerRegistration* JfrSerializerRegistration::next() const {
return _next;
}
~JfrSerializerRegistration() {
delete _serializer;
}
void JfrSerializerRegistration::set_next(JfrSerializerRegistration* next) {
_next = next;
}
JfrSerializerRegistration* next() const {
return _next;
}
JfrSerializerRegistration* JfrSerializerRegistration::prev() const {
return _prev;
}
void set_next(JfrSerializerRegistration* next) {
_next = next;
}
void JfrSerializerRegistration::set_prev(JfrSerializerRegistration* prev) {
_prev = prev;
}
JfrSerializerRegistration* prev() const {
return _prev;
}
JfrTypeId JfrSerializerRegistration::id() const {
return _id;
}
void set_prev(JfrSerializerRegistration* prev) {
_prev = prev;
}
void JfrSerializerRegistration::invoke_serializer(JfrCheckpointWriter& writer) const {
JfrTypeId id() const {
return _id;
}
void invoke(JfrCheckpointWriter& writer) const;
};
void JfrSerializerRegistration::invoke(JfrCheckpointWriter& writer) const {
if (_cache.valid()) {
writer.increment();
_cache->write(writer);
return;
}
const JfrCheckpointContext ctx = writer.context();
// serialize the type id before invoking callback
writer.write_type(_id);
const intptr_t start = writer.current_offset();
// invoke the serializer routine
_serializer->serialize(writer);
if (start == writer.current_offset() ) {
// the serializer implementation did nothing, rewind to restore
writer.set_context(ctx);
return;
}
if (_permit_cache) {
_cache = writer.copy(&ctx);
}
}
JfrTypeManager::~JfrTypeManager() {
Iterator iter(_types);
class SerializerRegistrationGuard : public StackObj {
private:
static Semaphore _mutex_semaphore;
public:
SerializerRegistrationGuard() {
_mutex_semaphore.wait();
}
~SerializerRegistrationGuard() {
_mutex_semaphore.signal();
}
};
Semaphore SerializerRegistrationGuard::_mutex_semaphore(1);
typedef JfrDoublyLinkedList<JfrSerializerRegistration> List;
typedef StopOnNullIterator<const List> Iterator;
static List types;
static List safepoint_types;
void JfrTypeManager::clear() {
SerializerRegistrationGuard guard;
Iterator iter(types);
JfrSerializerRegistration* registration;
while (iter.has_next()) {
registration = _types.remove(iter.next());
registration = types.remove(iter.next());
assert(registration != NULL, "invariant");
delete registration;
}
Iterator sp_type_iter(_safepoint_types);
Iterator sp_type_iter(safepoint_types);
while (sp_type_iter.has_next()) {
registration = _safepoint_types.remove(sp_type_iter.next());
registration = safepoint_types.remove(sp_type_iter.next());
assert(registration != NULL, "invariant");
delete registration;
}
}
size_t JfrTypeManager::number_of_registered_types() const {
size_t count = 0;
const Iterator iter(_types);
void JfrTypeManager::write_types(JfrCheckpointWriter& writer) {
const Iterator iter(types);
while (iter.has_next()) {
++count;
iter.next();
}
const Iterator sp_type_iter(_safepoint_types);
while (sp_type_iter.has_next()) {
++count;
sp_type_iter.next();
}
return count;
}
void JfrTypeManager::write_types(JfrCheckpointWriter& writer) const {
const Iterator iter(_types);
while (iter.has_next()) {
iter.next()->invoke_serializer(writer);
iter.next()->invoke(writer);
}
}
void JfrTypeManager::write_safepoint_types(JfrCheckpointWriter& writer) const {
void JfrTypeManager::write_safepoint_types(JfrCheckpointWriter& writer) {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
const Iterator iter(_safepoint_types);
const Iterator iter(safepoint_types);
while (iter.has_next()) {
iter.next()->invoke_serializer(writer);
iter.next()->invoke(writer);
}
}
void JfrTypeManager::write_type_set() const {
void JfrTypeManager::write_type_set() {
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
// can safepoint here because of Module_lock
MutexLockerEx lock(Module_lock);
@ -132,14 +156,14 @@ void JfrTypeManager::write_type_set() const {
set.serialize(writer);
}
void JfrTypeManager::write_type_set_for_unloaded_classes() const {
void JfrTypeManager::write_type_set_for_unloaded_classes() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
JfrCheckpointWriter writer(false, true, Thread::current());
ClassUnloadTypeSet class_unload_set;
class_unload_set.serialize(writer);
}
void JfrTypeManager::create_thread_checkpoint(JavaThread* jt) const {
void JfrTypeManager::create_thread_checkpoint(JavaThread* jt) {
assert(jt != NULL, "invariant");
JfrThreadConstant type_thread(jt);
JfrCheckpointWriter writer(false, true, jt);
@ -150,7 +174,7 @@ void JfrTypeManager::create_thread_checkpoint(JavaThread* jt) const {
assert(jt->jfr_thread_local()->has_thread_checkpoint(), "invariant");
}
void JfrTypeManager::write_thread_checkpoint(JavaThread* jt) const {
void JfrTypeManager::write_thread_checkpoint(JavaThread* jt) {
assert(jt != NULL, "JavaThread is NULL!");
ResourceMark rm(jt);
if (jt->jfr_thread_local()->has_thread_checkpoint()) {
@ -165,71 +189,64 @@ void JfrTypeManager::write_thread_checkpoint(JavaThread* jt) const {
}
#ifdef ASSERT
static void assert_not_registered_twice(JfrTypeId id, JfrTypeManager::List& list) {
const JfrTypeManager::Iterator iter(list);
static void assert_not_registered_twice(JfrTypeId id, List& list) {
const Iterator iter(list);
while (iter.has_next()) {
assert(iter.next()->id() != id, "invariant");
}
}
#endif
bool JfrTypeManager::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* cs) {
assert(cs != NULL, "invariant");
JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, cs);
static bool register_type(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) {
assert(serializer != NULL, "invariant");
JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer);
if (registration == NULL) {
delete cs;
delete serializer;
return false;
}
if (require_safepoint) {
assert(!_safepoint_types.in_list(registration), "invariant");
DEBUG_ONLY(assert_not_registered_twice(id, _safepoint_types);)
_safepoint_types.prepend(registration);
}
else {
assert(!_types.in_list(registration), "invariant");
DEBUG_ONLY(assert_not_registered_twice(id, _types);)
_types.prepend(registration);
assert(!safepoint_types.in_list(registration), "invariant");
DEBUG_ONLY(assert_not_registered_twice(id, safepoint_types);)
safepoint_types.prepend(registration);
} else {
assert(!types.in_list(registration), "invariant");
DEBUG_ONLY(assert_not_registered_twice(id, types);)
types.prepend(registration);
}
return true;
}
bool JfrTypeManager::initialize() {
SerializerRegistrationGuard guard;
// register non-safepointing type serialization
for (size_t i = 0; i < 18; ++i) {
switch (i) {
case 0: register_serializer(TYPE_FLAGVALUEORIGIN, false, true, new FlagValueOriginConstant()); break;
case 1: register_serializer(TYPE_INFLATECAUSE, false, true, new MonitorInflateCauseConstant()); break;
case 2: register_serializer(TYPE_GCCAUSE, false, true, new GCCauseConstant()); break;
case 3: register_serializer(TYPE_GCNAME, false, true, new GCNameConstant()); break;
case 4: register_serializer(TYPE_GCWHEN, false, true, new GCWhenConstant()); break;
case 5: register_serializer(TYPE_G1HEAPREGIONTYPE, false, true, new G1HeapRegionTypeConstant()); break;
case 6: register_serializer(TYPE_GCTHRESHOLDUPDATER, false, true, new GCThresholdUpdaterConstant()); break;
case 7: register_serializer(TYPE_METADATATYPE, false, true, new MetadataTypeConstant()); break;
case 8: register_serializer(TYPE_METASPACEOBJECTTYPE, false, true, new MetaspaceObjectTypeConstant()); break;
case 9: register_serializer(TYPE_G1YCTYPE, false, true, new G1YCTypeConstant()); break;
case 10: register_serializer(TYPE_REFERENCETYPE, false, true, new ReferenceTypeConstant()); break;
case 11: register_serializer(TYPE_NARROWOOPMODE, false, true, new NarrowOopModeConstant()); break;
case 12: register_serializer(TYPE_COMPILERPHASETYPE, false, true, new CompilerPhaseTypeConstant()); break;
case 13: register_serializer(TYPE_CODEBLOBTYPE, false, true, new CodeBlobTypeConstant()); break;
case 14: register_serializer(TYPE_VMOPERATIONTYPE, false, true, new VMOperationTypeConstant()); break;
case 15: register_serializer(TYPE_THREADSTATE, false, true, new ThreadStateConstant()); break;
case 16: register_serializer(TYPE_ZSTATISTICSCOUNTERTYPE, false, true, new ZStatisticsCounterTypeConstant()); break;
case 17: register_serializer(TYPE_ZSTATISTICSSAMPLERTYPE, false, true, new ZStatisticsSamplerTypeConstant()); break;
default:
guarantee(false, "invariant");
}
}
register_type(TYPE_FLAGVALUEORIGIN, false, true, new FlagValueOriginConstant());
register_type(TYPE_INFLATECAUSE, false, true, new MonitorInflateCauseConstant());
register_type(TYPE_GCCAUSE, false, true, new GCCauseConstant());
register_type(TYPE_GCNAME, false, true, new GCNameConstant());
register_type(TYPE_GCWHEN, false, true, new GCWhenConstant());
register_type(TYPE_G1HEAPREGIONTYPE, false, true, new G1HeapRegionTypeConstant());
register_type(TYPE_GCTHRESHOLDUPDATER, false, true, new GCThresholdUpdaterConstant());
register_type(TYPE_METADATATYPE, false, true, new MetadataTypeConstant());
register_type(TYPE_METASPACEOBJECTTYPE, false, true, new MetaspaceObjectTypeConstant());
register_type(TYPE_G1YCTYPE, false, true, new G1YCTypeConstant());
register_type(TYPE_REFERENCETYPE, false, true, new ReferenceTypeConstant());
register_type(TYPE_NARROWOOPMODE, false, true, new NarrowOopModeConstant());
register_type(TYPE_COMPILERPHASETYPE, false, true, new CompilerPhaseTypeConstant());
register_type(TYPE_CODEBLOBTYPE, false, true, new CodeBlobTypeConstant());
register_type(TYPE_VMOPERATIONTYPE, false, true, new VMOperationTypeConstant());
register_type(TYPE_THREADSTATE, false, true, new ThreadStateConstant());
register_type(TYPE_ZSTATISTICSCOUNTERTYPE, false, true, new ZStatisticsCounterTypeConstant());
register_type(TYPE_ZSTATISTICSSAMPLERTYPE, false, true, new ZStatisticsSamplerTypeConstant());
// register safepointing type serialization
for (size_t i = 0; i < 2; ++i) {
switch (i) {
case 0: register_serializer(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant()); break;
case 1: register_serializer(TYPE_THREAD, true, false, new JfrThreadConstantSet()); break;
default:
guarantee(false, "invariant");
}
}
register_type(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant());
register_type(TYPE_THREAD, true, false, new JfrThreadConstantSet());
return true;
}
// implementation for the static registration function exposed in the JfrSerializer api
bool JfrSerializer::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) {
SerializerRegistrationGuard guard;
return register_type(id, require_safepoint, permit_cache, serializer);
}

View File

@ -24,49 +24,21 @@
#ifndef SHARE_VM_JFR_CHECKPOINT_TYPES_JFRTYPEMANAGER_HPP
#define SHARE_VM_JFR_CHECKPOINT_TYPES_JFRTYPEMANAGER_HPP
#include "jfr/metadata/jfrSerializer.hpp"
#include "jfr/utilities/jfrAllocation.hpp"
#include "jfr/utilities/jfrDoublyLinkedList.hpp"
#include "jfr/utilities/jfrIterator.hpp"
class JfrSerializerRegistration : public JfrCHeapObj {
private:
JfrSerializerRegistration* _next;
JfrSerializerRegistration* _prev;
JfrSerializer* _serializer;
mutable JfrCheckpointBlobHandle _cache;
JfrTypeId _id;
bool _permit_cache;
class JavaThread;
class JfrCheckpointWriter;
class JfrTypeManager : public AllStatic {
public:
JfrSerializerRegistration(JfrTypeId id, bool permit_cache, JfrSerializer* serializer);
~JfrSerializerRegistration();
JfrSerializerRegistration* next() const;
void set_next(JfrSerializerRegistration* next);
JfrSerializerRegistration* prev() const;
void set_prev(JfrSerializerRegistration* prev);
void invoke_serializer(JfrCheckpointWriter& writer) const;
JfrTypeId id() const;
static bool initialize();
static void clear();
static void write_types(JfrCheckpointWriter& writer);
static void write_safepoint_types(JfrCheckpointWriter& writer);
static void write_type_set();
static void write_type_set_for_unloaded_classes();
static void create_thread_checkpoint(JavaThread* jt);
static void write_thread_checkpoint(JavaThread* jt);
};
class JfrTypeManager : public JfrCHeapObj {
friend class JfrCheckpointManager;
public:
typedef JfrDoublyLinkedList<JfrSerializerRegistration> List;
typedef StopOnNullIterator<const List> Iterator;
private:
List _types;
List _safepoint_types;
~JfrTypeManager();
bool initialize();
size_t number_of_registered_types() const;
void write_types(JfrCheckpointWriter& writer) const;
void write_safepoint_types(JfrCheckpointWriter& writer) const;
void write_type_set() const;
void write_type_set_for_unloaded_classes() const;
void create_thread_checkpoint(JavaThread* jt) const;
void write_thread_checkpoint(JavaThread* jt) const;
bool register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer);
};
#endif // SHARE_VM_JFR_CHECKPOINT_TYPES_JFRTYPEMANAGER_HPP