optimizations for old object sample metadata JEP-349-branch
authormgronlun
Thu, 29 Aug 2019 12:53:05 +0200
branchJEP-349-branch
changeset 57934 9c150f2b1fea
parent 57922 6598f2825b1f
child 57935 123705b84980
optimizations for old object sample metadata
src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp
src/hotspot/share/jfr/leakprofiler/sampling/objectSample.hpp
src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp
src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp
src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp
src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.hpp
src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.hpp
src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp
src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp	Thu Aug 29 12:53:05 2019 +0200
@@ -106,28 +106,28 @@
   return unloaded_thread_id_set != NULL && predicate(unloaded_thread_id_set, tid);
 }
 
-static GrowableArray<traceid>* unloaded_set = NULL;
+static GrowableArray<traceid>* unloaded_klass_set = NULL;
 
-static void sort_unloaded_set() {
-  if (unloaded_set != NULL) {
-    sort_array(unloaded_set);
+static void sort_unloaded_klass_set() {
+  if (unloaded_klass_set != NULL) {
+    sort_array(unloaded_klass_set);
   }
 }
 
-static void add_to_unloaded_set(traceid klass_id) {
-  if (unloaded_set == NULL) {
-    unloaded_set = c_heap_allocate_array<traceid>();
+static void add_to_unloaded_klass_set(traceid klass_id) {
+  if (unloaded_klass_set == NULL) {
+    unloaded_klass_set = c_heap_allocate_array<traceid>();
   }
-  unloaded_set->append(klass_id);
+  unloaded_klass_set->append(klass_id);
 }
 
 void ObjectSampleCheckpoint::on_klass_unload(const Klass* k) {
   assert(k != NULL, "invariant");
-  add_to_unloaded_set(TRACE_ID(k));
+  add_to_unloaded_klass_set(TRACE_ID(k));
 }
 
 static bool is_klass_unloaded(traceid klass_id) {
-  return unloaded_set != NULL && predicate(unloaded_set, klass_id);
+  return unloaded_klass_set != NULL && predicate(unloaded_klass_set, klass_id);
 }
 
 static GrowableArray<traceid>* id_set = NULL;
@@ -164,15 +164,12 @@
 }
 
 template <typename Processor>
-static void iterate_samples(Processor& processor, bool all = false, bool update_last_resolved = false) {
+static void iterate_samples(Processor& processor, bool all = false) {
   ObjectSampler* const sampler = ObjectSampler::sampler();
   assert(sampler != NULL, "invariant");
   ObjectSample* const last = sampler->last();
   assert(last != NULL, "invariant");
   do_samples(last, all ? NULL : sampler->last_resolved(), processor);
-  if (update_last_resolved) {
-    sampler->set_last_resolved(last);
-  }
 }
 
 void ObjectSampleCheckpoint::on_thread_exit(JavaThread* jt) {
@@ -182,66 +179,41 @@
   }
 }
 
-class CheckpointInstall {
+class CheckpointBlobInstaller {
  private:
   const JfrCheckpointBlobHandle& _cp;
  public:
-  CheckpointInstall(const JfrCheckpointBlobHandle& cp) : _cp(cp) {}
+  CheckpointBlobInstaller(const JfrCheckpointBlobHandle& cp) : _cp(cp) {}
   void sample_do(ObjectSample* sample) {
-    assert(sample != NULL, "invariant");
     if (!sample->is_dead()) {
       sample->set_klass_checkpoint(_cp);
     }
   }
 };
 
-static void install_blob(JfrCheckpointWriter& writer) {
+static void install_checkpoint_blob(JfrCheckpointWriter& writer) {
   assert(writer.has_data(), "invariant");
   const JfrCheckpointBlobHandle h_cp = writer.copy();
-  CheckpointInstall install(h_cp);
-  iterate_samples(install, true, false);
+  CheckpointBlobInstaller installer(h_cp);
+  iterate_samples(installer, true);
 }
 
 void ObjectSampleCheckpoint::on_type_set_unload(JfrCheckpointWriter& writer) {
   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   assert(LeakProfiler::is_running(), "invariant");
   if (writer.has_data() && ObjectSampler::sampler()->last() != NULL) {
-    install_blob(writer);
+    install_checkpoint_blob(writer);
   }
 }
 
-class ObjectResolver {
- public:
-  ObjectResolver() {}
-  void sample_do(ObjectSample* sample) {
-    assert(sample != NULL, "invariant");
-    const traceid klass_id = sample->_klass_id;
-    if (klass_id != 0 || sample->is_dead() || is_klass_unloaded(klass_id)) {
-      return;
-    }
-    sample->_klass_id = JfrTraceId::use(sample->klass());
-  }
-};
-
-void ObjectSampleCheckpoint::resolve_sampled_objects() {
-  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
-  assert(LeakProfiler::is_running(), "invariant");
-  if (ObjectSampler::sampler()->last() == NULL) {
-    return;
-  }
-  ObjectResolver resolver;
-  iterate_samples(resolver, false, true);
-}
-
-class SampleMark {
+class SampleMarker {
  private:
   ObjectSampleMarker& _marker;
   jlong _last_sweep;
   int _count;
  public:
-  SampleMark(ObjectSampleMarker& marker, jlong last_sweep) : _marker(marker), _last_sweep(last_sweep), _count(0) {}
+  SampleMarker(ObjectSampleMarker& marker, jlong last_sweep) : _marker(marker), _last_sweep(last_sweep), _count(0) {}
   void sample_do(ObjectSample* sample) {
-    assert(sample != NULL, "invariant");
     if (sample->is_alive_and_older_than(_last_sweep)) {
       _marker.mark(sample->object());
       ++_count;
@@ -257,17 +229,9 @@
   if (sampler->last() == NULL) {
     return 0;
   }
-  SampleMark mark(marker, emit_all ? max_jlong : sampler->last_sweep().value());
-  iterate_samples(mark, true, false);
-  return mark.count();
-}
-
-void ObjectSampleCheckpoint::tag(const ObjectSample* sample) {
-  assert(sample != NULL, "invariant");
-  const traceid klass_id = sample->_klass_id;
-  if (should_process(sample->_klass_id)) {
-    JfrTraceId::use(sample->klass());
-  }
+  SampleMarker sample_marker(marker, emit_all ? max_jlong : sampler->last_sweep().value());
+  iterate_samples(sample_marker, true);
+  return sample_marker.count();
 }
 
 #ifdef ASSERT
@@ -368,13 +332,12 @@
   return sample->has_stack_trace_id() && !sample->is_dead();
 }
 
-class Tagger {
+class StackTraceTagger {
  private:
   JfrStackTraceRepository& _stack_trace_repo;
  public:
-  Tagger(JfrStackTraceRepository& stack_trace_repo) : _stack_trace_repo(stack_trace_repo) {}
+  StackTraceTagger(JfrStackTraceRepository& stack_trace_repo) : _stack_trace_repo(stack_trace_repo) {}
   void sample_do(ObjectSample* sample) {
-    ObjectSampleCheckpoint::tag(sample);
     if (stack_trace_precondition(sample)) {
       assert(sample->stack_trace_id() == sample->stack_trace()->id(), "invariant");
       ObjectSampleCheckpoint::tag(sample->stack_trace(), NULL);
@@ -382,22 +345,21 @@
   }
 };
 
-static void tag_old_traces(ObjectSample* last_resolved, JfrStackTraceRepository& stack_trace_repo) {
+static void tag_old_stack_traces(ObjectSample* last_resolved, JfrStackTraceRepository& stack_trace_repo) {
   assert(last_resolved != NULL, "invariant");
   assert(stack_trace_id_set != NULL, "invariant");
   assert(stack_trace_id_set->is_empty(), "invariant");
-  Tagger tagger(stack_trace_repo);
+  StackTraceTagger tagger(stack_trace_repo);
   do_samples(last_resolved, NULL, tagger);
 }
 
-class StackTraceInstall {
+class StackTraceResolver {
  private:
   JfrStackTraceRepository& _stack_trace_repo;
  public:
-  StackTraceInstall(JfrStackTraceRepository& stack_trace_repo) : _stack_trace_repo(stack_trace_repo) {}
+  StackTraceResolver(JfrStackTraceRepository& stack_trace_repo) : _stack_trace_repo(stack_trace_repo) {}
   void install_to_sample(ObjectSample* sample, const JfrStackTrace* stack_trace);
   void sample_do(ObjectSample* sample) {
-    ObjectSampleCheckpoint::tag(sample);
     if (stack_trace_precondition(sample)) {
       install_to_sample(sample, _stack_trace_repo.lookup(sample->stack_trace_hash(), sample->stack_trace_id()));
     }
@@ -405,53 +367,57 @@
 };
 
 #ifdef ASSERT
-static void validate_stack_trace(const ObjectSample* sample, const JfrStackTrace* trace) {
+static void validate_stack_trace(const ObjectSample* sample, const JfrStackTrace* stack_trace) {
   assert(sample != NULL, "invariant");
-  assert(trace != NULL, "invariant");
-  assert(trace->hash() == sample->stack_trace_hash(), "invariant");
-  assert(trace->id() == sample->stack_trace_id(), "invariant");
+  assert(!sample->is_dead(), "invariant");
+  assert(stack_trace != NULL, "invariant");
+  assert(stack_trace->hash() == sample->stack_trace_hash(), "invariant");
+  assert(stack_trace->id() == sample->stack_trace_id(), "invariant");
 }
 #endif
 
-void StackTraceInstall::install_to_sample(ObjectSample* sample, const JfrStackTrace* stack_trace) {
-  assert(sample != NULL, "invariant");
-  assert(stack_trace != NULL, "invariant");
+void StackTraceResolver::install_to_sample(ObjectSample* sample, const JfrStackTrace* stack_trace) {
   DEBUG_ONLY(validate_stack_trace(sample, stack_trace));
-  JfrStackTrace* const sample_trace = const_cast<JfrStackTrace*>(sample->stack_trace());
-  if (sample_trace != NULL && sample_trace->id() != stack_trace->id()) {
-    *sample_trace = *stack_trace; // copy
+  JfrStackTrace* const sample_stack_trace = const_cast<JfrStackTrace*>(sample->stack_trace());
+  if (sample_stack_trace != NULL) {
+    if (sample_stack_trace->id() != stack_trace->id()) {
+      *sample_stack_trace = *stack_trace; // copy
+    }
   } else {
     sample->set_stack_trace(new JfrStackTrace(stack_trace->id(), *stack_trace, NULL)); // new
   }
   assert(sample->stack_trace() != NULL, "invariant");
 }
 
-static void install_new_stack_traces(JfrStackTraceRepository& stack_trace_repo) {
-  StackTraceInstall stack_trace_install(stack_trace_repo);
-  iterate_samples(stack_trace_install);
-  stack_trace_id_set->clear();
-}
-
 static void allocate_traceid_working_sets() {
   const int set_size = JfrOptionSet::old_object_queue_size();
   stack_trace_id_set = resource_allocate_array<traceid>(set_size);
   id_set = resource_allocate_array<traceid>(set_size);
-  sort_unloaded_set();
+  sort_unloaded_klass_set();
+}
+
+static void resolve_stack_traces(JfrStackTraceRepository& stack_trace_repo) {
+  StackTraceResolver stack_trace_resolver(stack_trace_repo);
+  iterate_samples(stack_trace_resolver);
 }
 
 // caller needs ResourceMark
-void ObjectSampleCheckpoint::rotate(const ObjectSampler* sampler, JfrStackTraceRepository& stack_trace_repo) {
+void ObjectSampleCheckpoint::on_rotation(ObjectSampler* sampler, JfrStackTraceRepository& stack_trace_repo) {
   assert(sampler != NULL, "invariant");
   assert(LeakProfiler::is_running(), "invariant");
-  if (sampler->last() == NULL) {
+  const ObjectSample* const last = sampler->last();
+  if (last == NULL) {
     // nothing to process
     return;
   }
-  allocate_traceid_working_sets();
-  install_new_stack_traces(stack_trace_repo);
   ObjectSample* const last_resolved = const_cast<ObjectSample*>(sampler->last_resolved());
   if (last_resolved != NULL) {
-    tag_old_traces(last_resolved, stack_trace_repo);
+    allocate_traceid_working_sets();
+    tag_old_stack_traces(last_resolved, stack_trace_repo);
+  }
+  if (last != last_resolved) {
+    resolve_stack_traces(stack_trace_repo);
+    sampler->set_last_resolved(last);
   }
 }
 
@@ -516,30 +482,28 @@
   write_klass_blob(sample, writer);
 }
 
-class CheckpointWrite {
+class CheckpointBlobWriter {
  private:
   const ObjectSampler* _sampler;
   JfrCheckpointWriter& _writer;
   const jlong _last_sweep;
  public:
-  CheckpointWrite(const ObjectSampler* sampler, JfrCheckpointWriter& writer, jlong last_sweep) :
+  CheckpointBlobWriter(const ObjectSampler* sampler, JfrCheckpointWriter& writer, jlong last_sweep) :
     _sampler(sampler), _writer(writer), _last_sweep(last_sweep) {}
   void sample_do(ObjectSample* sample) {
-    assert(sample != NULL, "invariant");
     if (sample->is_alive_and_older_than(_last_sweep)) {
       write_blobs(sample, _writer);
     }
   }
 };
 
-class CheckpointStateReset {
+class CheckpointBlobStateReset {
  private:
   const ObjectSampler* _sampler;
   const jlong _last_sweep;
  public:
-  CheckpointStateReset(const ObjectSampler* sampler, jlong last_sweep) : _sampler(sampler), _last_sweep(last_sweep) {}
+  CheckpointBlobStateReset(const ObjectSampler* sampler, jlong last_sweep) : _sampler(sampler), _last_sweep(last_sweep) {}
   void sample_do(ObjectSample* sample) {
-    assert(sample != NULL, "invariant");
     if (sample->is_alive_and_older_than(_last_sweep)) {
       reset_blob_write_state(sample);
     }
@@ -547,32 +511,33 @@
 };
 
 static void reset_write_state_for_blobs(const ObjectSampler* sampler, jlong last_sweep) {
-  CheckpointStateReset state_reset(sampler, last_sweep);
-  iterate_samples(state_reset, true, false);
+  CheckpointBlobStateReset state_reset(sampler, last_sweep);
+  iterate_samples(state_reset, true);
 }
 
 static void write_sample_blobs(const ObjectSampler* sampler, jlong last_sweep, Thread* thread) {
   JfrCheckpointWriter writer(thread, false);
-  CheckpointWrite checkpoint_write(sampler, writer, last_sweep);
-  iterate_samples(checkpoint_write, true, false);
+  CheckpointBlobWriter cbw(sampler, writer, last_sweep);
+  iterate_samples(cbw, true);
   reset_write_state_for_blobs(sampler, last_sweep);
 }
 
-class StackTraceWrite {
+class StackTraceWriter {
  private:
   JfrStackTraceRepository& _stack_trace_repo;
   JfrCheckpointWriter& _writer;
   const jlong _last_sweep;
   int _count;
  public:
-  StackTraceWrite(JfrStackTraceRepository& stack_trace_repo, JfrCheckpointWriter& writer, jlong last_sweep) :
+  StackTraceWriter(JfrStackTraceRepository& stack_trace_repo, JfrCheckpointWriter& writer, jlong last_sweep) :
     _stack_trace_repo(stack_trace_repo), _writer(writer), _last_sweep(last_sweep), _count(0) {}
   void sample_do(ObjectSample* sample) {
-    ObjectSampleCheckpoint::tag(sample);
-    if (stack_trace_precondition(sample) && sample->is_alive_and_older_than(_last_sweep)) {
-      assert(sample->stack_trace_id() == sample->stack_trace()->id(), "invariant");
-      if (ObjectSampleCheckpoint::tag(sample->stack_trace(), &_writer)) {
-        ++_count;
+    if (sample->is_alive_and_older_than(_last_sweep)) {
+      if (stack_trace_precondition(sample)) {
+        assert(sample->stack_trace_id() == sample->stack_trace()->id(), "invariant");
+        if (ObjectSampleCheckpoint::tag(sample->stack_trace(), &_writer)) {
+          ++_count;
+        }
       }
     }
   }
@@ -584,12 +549,12 @@
 static void write_and_tag_stack_traces(const ObjectSampler* sampler, JfrStackTraceRepository& repo, jlong last_sweep, Thread* thread) {
   assert(sampler != NULL, "invariant");
   allocate_traceid_working_sets();
-  install_new_stack_traces(repo);
+  resolve_stack_traces(repo);
   JfrCheckpointWriter writer(thread);
   const JfrCheckpointContext ctx = writer.context();
   writer.write_type(TYPE_STACKTRACE);
   const jlong count_offset = writer.reserve(sizeof(u4));
-  StackTraceWrite sw(repo, writer, last_sweep);
+  StackTraceWriter sw(repo, writer, last_sweep);
   do_samples(sampler->last(), NULL, sw);
   if (sw.count() == 0) {
     writer.set_context(ctx);
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp	Thu Aug 29 12:53:05 2019 +0200
@@ -43,9 +43,7 @@
   static void on_klass_unload(const Klass* k);
   static void on_type_set_unload(JfrCheckpointWriter& writer);
   static void on_thread_exit(JavaThread* jt);
-  static void resolve_sampled_objects();
-  static void rotate(const ObjectSampler* sampler, JfrStackTraceRepository& repo);
-  static void tag(const ObjectSample* sample);
+  static void on_rotation(ObjectSampler* sampler, JfrStackTraceRepository& repo);
   static bool tag(const JfrStackTrace* trace, JfrCheckpointWriter* writer = NULL);
   static int save_mark_words(const ObjectSampler* sampler, ObjectSampleMarker& marker, bool emit_all);
   static void write(const ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread);
--- a/src/hotspot/share/jfr/leakprofiler/sampling/objectSample.hpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/leakprofiler/sampling/objectSample.hpp	Thu Aug 29 12:53:05 2019 +0200
@@ -56,7 +56,6 @@
   Ticks _allocation_time;
   traceid _stack_trace_id;
   traceid _thread_id;
-  mutable traceid _klass_id;
   int _index;
   size_t _span;
   size_t _allocated;
@@ -80,7 +79,6 @@
   void reset() {
     set_stack_trace_id(0);
     set_stack_trace_hash(0);
-    _klass_id = 0;
     release_references();
     _dead = false;
   }
@@ -101,7 +99,6 @@
                    _allocation_time(),
                    _stack_trace_id(0),
                    _thread_id(0),
-                   _klass_id(0),
                    _index(0),
                    _span(0),
                    _allocated(0),
--- a/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp	Thu Aug 29 12:53:05 2019 +0200
@@ -110,6 +110,9 @@
   }
   const JfrThreadLocal* const tl = thread->jfr_thread_local();
   assert(tl != NULL, "invariant");
+  if (tl->is_excluded()) {
+    return 0;
+  }
   if (!tl->has_thread_checkpoint()) {
     JfrCheckpointManager::create_thread_checkpoint(thread);
   }
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp	Thu Aug 29 12:53:05 2019 +0200
@@ -439,16 +439,24 @@
   JfrTypeManager::write_type_set_for_unloaded_classes();
 }
 
-bool JfrCheckpointManager::is_type_set_checkpoint_required() const {
+bool JfrCheckpointManager::is_type_set_required() {
   return JfrTraceIdEpoch::is_klass_tagged_in_epoch();
 }
 
+bool JfrCheckpointManager::is_constant_set_required() {
+  return JfrTypeManager::is_new_constant_registered();
+}
+
 size_t JfrCheckpointManager::flush_type_set() {
   const size_t elements = JfrTypeManager::flush_type_set();
   flush();
   return elements;
 }
 
+void JfrCheckpointManager::flush_constant_set() {
+  flush();
+}
+
 void JfrCheckpointManager::create_thread_checkpoint(Thread* t) {
   JfrTypeManager::create_thread_checkpoint(t);
 }
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp	Thu Aug 29 12:53:05 2019 +0200
@@ -88,6 +88,8 @@
   bool use_epoch_transition_mspace(const Thread* t) const;
   void notify_threads();
   void notify_types_on_rotation();
+  bool is_type_set_required();
+  bool is_constant_set_required();
 
   JfrCheckpointManager(JfrChunkWriter& cw);
   ~JfrCheckpointManager();
@@ -99,8 +101,8 @@
 
  public:
   void register_service_thread(const Thread* t);
-  bool is_type_set_checkpoint_required() const;
   size_t flush_type_set();
+  void flush_constant_set();
   static void write_type_set_for_unloaded_classes();
   static void create_thread_checkpoint(Thread* t);
   static void write_thread_checkpoint(Thread* t);
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp	Thu Aug 29 12:53:05 2019 +0200
@@ -134,11 +134,15 @@
   }
 }
 
+static bool new_registration = false;
+
 void JfrTypeManager::write_types(JfrCheckpointWriter& writer) {
+  SerializerRegistrationGuard guard;
   const Iterator iter(types);
   while (iter.has_next()) {
     iter.next()->invoke(writer);
   }
+  new_registration = false;
 }
 
 static void serialize_threads(JfrCheckpointWriter& writer) {
@@ -235,8 +239,9 @@
   assert(!types.in_list(registration), "invariant");
   DEBUG_ONLY(assert_not_registered_twice(id, types);)
   if (Jfr::is_recording()) {
-    JfrCheckpointWriter writer;
+    JfrCheckpointWriter writer(STATICS);
     registration->invoke(writer);
+    new_registration = true;
   }
   types.prepend(registration);
   return true;
@@ -268,3 +273,12 @@
   SerializerRegistrationGuard guard;
   return register_type(id, permit_cache, serializer);
 }
+
+bool JfrTypeManager::is_new_constant_registered() {
+  if (new_registration) {
+    SerializerRegistrationGuard guard;
+    new_registration = false;
+    return true;
+  }
+  return false;
+}
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.hpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.hpp	Thu Aug 29 12:53:05 2019 +0200
@@ -33,6 +33,7 @@
  public:
   static bool initialize();
   static void clear();
+  static bool is_new_constant_registered();
   static void write_types(JfrCheckpointWriter& writer);
   static void write_threads(JfrCheckpointWriter& writer);
   static void notify_types_on_rotation();
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Thu Aug 29 12:53:05 2019 +0200
@@ -614,8 +614,11 @@
   if (_string_pool.is_modified()) {
     total_elements += flush_stringpool(_string_pool, _chunkwriter);
   }
-  if (_checkpoint_manager.is_type_set_checkpoint_required()) {
+  if (_checkpoint_manager.is_type_set_required()) {
     total_elements += flush_typeset(_checkpoint_manager, _chunkwriter);
+  } else if (_checkpoint_manager.is_constant_set_required()) {
+    // don't tally this, it is only in order to flush the waiting constants
+    _checkpoint_manager.flush_constant_set();
   }
   return total_elements;
 }
@@ -653,7 +656,7 @@
   if (LeakProfiler::is_running()) {
     // Exclusive access to the object sampler instance.
     // The sampler is released (unlocked) later in post_safepoint_write.
-    ObjectSampleCheckpoint::rotate(ObjectSampler::acquire(), _stack_trace_repository);
+    ObjectSampleCheckpoint::on_rotation(ObjectSampler::acquire(), _stack_trace_repository);
   }
   _checkpoint_manager.notify_types_on_rotation();
   _storage.write();
@@ -681,9 +684,6 @@
   if (_string_pool.is_modified()) {
     flush_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter);
   }
-  if (LeakProfiler::is_running()) {
-    ObjectSampleCheckpoint::resolve_sampled_objects();
-  }
   _storage.write_at_safepoint();
   _checkpoint_manager.notify_threads();
   _checkpoint_manager.shift_epoch();
--- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.hpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.hpp	Thu Aug 29 12:53:05 2019 +0200
@@ -69,7 +69,7 @@
   friend class ObjectSampler;
   friend class OSThreadSampler;
   friend class ProcessStackTrace;
-  friend class StackTraceInstall;
+  friend class StackTraceResolver;
   friend class StackTraceWrite;
 
  private:
--- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp	Thu Aug 29 12:53:05 2019 +0200
@@ -177,18 +177,15 @@
   return tid;
 }
 
-traceid JfrStackTraceRepository::record_and_cache(JavaThread* thread, int skip /* 0 */) {
+void JfrStackTraceRepository::record_and_cache(JavaThread* thread, int skip /* 0 */) {
+  assert(thread != NULL, "invariant");
   JfrThreadLocal* const tl = thread->jfr_thread_local();
   assert(tl != NULL, "invariant");
-  if (tl->has_cached_stack_trace()) {
-    return tl->cached_stack_trace_id();
-  }
+  assert(!tl->has_cached_stack_trace(), "invariant");
   JfrStackTrace stacktrace(tl->stackframes(), tl->stackdepth());
   stacktrace.record_safe(thread, skip);
   assert(stacktrace.hash() != 0, "invariant");
-  const traceid id = instance().add(stacktrace);
-  tl->set_cached_stack_trace_id(id, stacktrace.hash());
-  return id;
+  tl->set_cached_stack_trace_id(instance().add(stacktrace), stacktrace.hash());
 }
 
 traceid JfrStackTraceRepository::add_trace(const JfrStackTrace& stacktrace) {
--- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp	Thu Aug 29 03:29:45 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp	Thu Aug 29 12:53:05 2019 +0200
@@ -40,7 +40,7 @@
   friend class JfrThreadSampleClosure;
   friend class ObjectSampleCheckpoint;
   friend class ObjectSampler;
-  friend class StackTraceInstall;
+  friend class StackTraceResolver;
   friend class StackTraceWrite;
   friend class WriteStackTraceRepository;
 
@@ -71,7 +71,7 @@
 
  public:
   static traceid record(Thread* thread, int skip = 0);
-  static traceid record_and_cache(JavaThread* thread, int skip = 0);
+  static void record_and_cache(JavaThread* thread, int skip = 0);
 };
 
 #endif // SHARE_JFR_RECORDER_STACKTRACE_JFRSTACKTRACEREPOSITORY_HPP