src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp
changeset 58863 c16ac7a2eba4
parent 58786 7909763ad193
--- 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;
+}