diff -r 2c3cc4b01880 -r c16ac7a2eba4 src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp Wed Oct 30 16:14:56 2019 +0100 +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp Wed Oct 30 19:43:52 2019 +0100 @@ -27,6 +27,7 @@ #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" #include "jfr/recorder/checkpoint/types/jfrType.hpp" #include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp" +#include "jfr/recorder/jfrRecorder.hpp" #include "jfr/utilities/jfrDoublyLinkedList.hpp" #include "jfr/utilities/jfrIterator.hpp" #include "memory/resourceArea.hpp" @@ -73,29 +74,71 @@ return _id; } - void invoke(JfrCheckpointWriter& writer) const; + void on_rotation() const { + _serializer->on_rotation(); + } + + void 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); + } + } }; -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); - } +static void serialize_threads(JfrCheckpointWriter& writer) { + JfrThreadConstantSet thread_set; + writer.write_type(TYPE_THREAD); + thread_set.serialize(writer); +} + +static void serialize_thread_groups(JfrCheckpointWriter& writer) { + JfrThreadGroupConstant thread_group_set; + writer.write_type(TYPE_THREADGROUP); + thread_group_set.serialize(writer); +} + +void JfrTypeManager::write_threads(JfrCheckpointWriter& writer) { + serialize_threads(writer); + serialize_thread_groups(writer); +} + +void JfrTypeManager::create_thread_blob(Thread* t) { + assert(t != NULL, "invariant"); + ResourceMark rm(t); + HandleMark hm(t); + JfrThreadConstant type_thread(t); + JfrCheckpointWriter writer(t, true, THREADS); + writer.write_type(TYPE_THREAD); + type_thread.serialize(writer); + // create and install a checkpoint blob + t->jfr_thread_local()->set_thread_blob(writer.move()); + assert(t->jfr_thread_local()->has_thread_blob(), "invariant"); +} + +void JfrTypeManager::write_thread_checkpoint(Thread* t) { + assert(t != NULL, "invariant"); + ResourceMark rm(t); + HandleMark hm(t); + JfrThreadConstant type_thread(t); + JfrCheckpointWriter writer(t, true, THREADS); + writer.write_type(TYPE_THREAD); + type_thread.serialize(writer); } class SerializerRegistrationGuard : public StackObj { @@ -115,7 +158,6 @@ typedef JfrDoublyLinkedList List; typedef StopOnNullIterator Iterator; static List types; -static List safepoint_types; void JfrTypeManager::destroy() { SerializerRegistrationGuard guard; @@ -126,52 +168,15 @@ assert(registration != NULL, "invariant"); delete registration; } - Iterator sp_type_iter(safepoint_types); - while (sp_type_iter.has_next()) { - registration = safepoint_types.remove(sp_type_iter.next()); - assert(registration != NULL, "invariant"); - delete registration; - } -} - -void JfrTypeManager::write_types(JfrCheckpointWriter& writer) { - const Iterator iter(types); - while (iter.has_next()) { - iter.next()->invoke(writer); - } } -void JfrTypeManager::write_safepoint_types(JfrCheckpointWriter& writer) { - assert(SafepointSynchronize::is_at_safepoint(), "invariant"); - const Iterator iter(safepoint_types); +void JfrTypeManager::on_rotation() { + const Iterator iter(types); while (iter.has_next()) { - iter.next()->invoke(writer); + iter.next()->on_rotation(); } } -void JfrTypeManager::create_thread_blob(JavaThread* jt) { - assert(jt != NULL, "invariant"); - ResourceMark rm(jt); - HandleMark hm(jt); - JfrThreadConstant type_thread(jt); - JfrCheckpointWriter writer(false, true, jt); - writer.write_type(TYPE_THREAD); - type_thread.serialize(writer); - // create and install a checkpoint blob - jt->jfr_thread_local()->set_thread_blob(writer.move()); - assert(jt->jfr_thread_local()->has_thread_blob(), "invariant"); -} - -void JfrTypeManager::write_thread_checkpoint(JavaThread* jt) { - assert(jt != NULL, "JavaThread is NULL!"); - ResourceMark rm(jt); - HandleMark hm(jt); - JfrThreadConstant type_thread(jt); - JfrCheckpointWriter writer(false, true, jt); - writer.write_type(TYPE_THREAD); - type_thread.serialize(writer); -} - #ifdef ASSERT static void assert_not_registered_twice(JfrTypeId id, List& list) { const Iterator iter(list); @@ -181,52 +186,65 @@ } #endif -static bool register_type(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) { +static bool new_registration = false; + +static bool register_static_type(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) { assert(serializer != NULL, "invariant"); JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer); if (registration == NULL) { 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(!types.in_list(registration), "invariant"); + DEBUG_ONLY(assert_not_registered_twice(id, types);) + if (JfrRecorder::is_recording()) { + JfrCheckpointWriter writer(STATICS); + registration->invoke(writer); + new_registration = true; } + types.prepend(registration); return true; } bool JfrTypeManager::initialize() { SerializerRegistrationGuard guard; - - // register non-safepointing type serialization - 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_GCTHRESHOLDUPDATER, false, true, new GCThresholdUpdaterConstant()); - register_type(TYPE_METADATATYPE, false, true, new MetadataTypeConstant()); - register_type(TYPE_METASPACEOBJECTTYPE, false, true, new MetaspaceObjectTypeConstant()); - 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 safepointing type serialization - register_type(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant()); - register_type(TYPE_THREAD, true, false, new JfrThreadConstantSet()); + register_static_type(TYPE_FLAGVALUEORIGIN, true, new FlagValueOriginConstant()); + register_static_type(TYPE_INFLATECAUSE, true, new MonitorInflateCauseConstant()); + register_static_type(TYPE_GCCAUSE, true, new GCCauseConstant()); + register_static_type(TYPE_GCNAME, true, new GCNameConstant()); + register_static_type(TYPE_GCWHEN, true, new GCWhenConstant()); + register_static_type(TYPE_GCTHRESHOLDUPDATER, true, new GCThresholdUpdaterConstant()); + register_static_type(TYPE_METADATATYPE, true, new MetadataTypeConstant()); + register_static_type(TYPE_METASPACEOBJECTTYPE, true, new MetaspaceObjectTypeConstant()); + register_static_type(TYPE_REFERENCETYPE, true, new ReferenceTypeConstant()); + register_static_type(TYPE_NARROWOOPMODE, true, new NarrowOopModeConstant()); + register_static_type(TYPE_COMPILERPHASETYPE, true, new CompilerPhaseTypeConstant()); + register_static_type(TYPE_CODEBLOBTYPE, true, new CodeBlobTypeConstant()); + register_static_type(TYPE_VMOPERATIONTYPE, true, new VMOperationTypeConstant()); + register_static_type(TYPE_THREADSTATE, true, new ThreadStateConstant()); 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) { +bool JfrSerializer::register_serializer(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) { SerializerRegistrationGuard guard; - return register_type(id, require_safepoint, permit_cache, serializer); + return register_static_type(id, permit_cache, serializer); } + +bool JfrTypeManager::has_new_static_type() { + if (new_registration) { + SerializerRegistrationGuard guard; + new_registration = false; + return true; + } + return false; +} + +void JfrTypeManager::write_static_types(JfrCheckpointWriter& writer) { + SerializerRegistrationGuard guard; + const Iterator iter(types); + while (iter.has_next()) { + iter.next()->invoke(writer); + } + new_registration = false; +}