--- 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<JfrSerializerRegistration> List;
typedef StopOnNullIterator<const List> 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;
+}