src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
changeset 58132 caa25ab47aca
parent 52586 74109912c738
child 58157 9dca61a7df19
child 58786 7909763ad193
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp	Fri Sep 13 16:03:31 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp	Sat Sep 14 14:40:09 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,32 +28,22 @@
 #include "classfile/moduleEntry.hpp"
 #include "classfile/packageEntry.hpp"
 #include "classfile/symbolTable.hpp"
-#include "classfile/systemDictionary.hpp"
 #include "jfr/jfr.hpp"
 #include "jfr/jni/jfrGetAllEventClasses.hpp"
-#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
+#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
 #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
-#include "jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp"
 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
-#include "jfr/recorder/storage/jfrBuffer.hpp"
 #include "jfr/utilities/jfrHashtable.hpp"
 #include "jfr/utilities/jfrTypes.hpp"
+#include "jfr/writers/jfrTypeWriterHost.hpp"
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "memory/resourceArea.hpp"
 #include "utilities/accessFlags.hpp"
 
-// incremented on each checkpoint
-static u8 checkpoint_id = 0;
-
-// creates a unique id by combining a checkpoint relative symbol id (2^24)
-// with the current checkpoint id (2^40)
-#define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))
-
 typedef const Klass* KlassPtr;
 typedef const PackageEntry* PkgPtr;
 typedef const ModuleEntry* ModPtr;
@@ -63,57 +53,112 @@
 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
 
-static traceid module_id(PkgPtr pkg) {
-  assert(pkg != NULL, "invariant");
-  ModPtr module_entry = pkg->module();
-  return module_entry != NULL && module_entry->is_named() ? TRACE_ID(module_entry) : 0;
+static JfrCheckpointWriter* _writer = NULL;
+static JfrCheckpointWriter* _leakp_writer = NULL;
+static JfrArtifactSet* _artifacts = NULL;
+static JfrArtifactClosure* _subsystem_callback = NULL;
+static bool _class_unload = false;
+static bool _flushpoint = false;
+
+// incremented on each rotation
+static u8 checkpoint_id = 1;
+
+// creates a unique id by combining a checkpoint relative symbol id (2^24)
+// with the current checkpoint id (2^40)
+#define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))
+
+static traceid create_symbol_id(traceid artifact_id) {
+  return artifact_id != 0 ? CREATE_SYMBOL_ID(artifact_id) : 0;
+}
+
+static bool current_epoch() {
+  return _class_unload;
 }
 
-static traceid package_id(KlassPtr klass) {
-  assert(klass != NULL, "invariant");
-  PkgPtr pkg_entry = klass->package();
-  return pkg_entry == NULL ? 0 : TRACE_ID(pkg_entry);
+static bool previous_epoch() {
+  return !current_epoch();
+}
+
+static bool is_complete() {
+  return !_artifacts->has_klass_entries() && current_epoch();
+}
+
+static traceid mark_symbol(KlassPtr klass, bool leakp) {
+  return klass != NULL ? create_symbol_id(_artifacts->mark(klass, leakp)) : 0;
 }
 
-static traceid cld_id(CldPtr cld) {
-  assert(cld != NULL, "invariant");
-  return cld->is_unsafe_anonymous() ? 0 : TRACE_ID(cld);
+static traceid mark_symbol(Symbol* symbol, bool leakp) {
+  return symbol != NULL ? create_symbol_id(_artifacts->mark(symbol, leakp)) : 0;
+}
+
+static traceid get_bootstrap_name(bool leakp) {
+  return create_symbol_id(_artifacts->bootstrap_name(leakp));
+}
+
+template <typename T>
+static traceid artifact_id(const T* ptr) {
+  assert(ptr != NULL, "invariant");
+  return TRACE_ID(ptr);
 }
 
-static void tag_leakp_klass_artifacts(KlassPtr k, bool class_unload) {
-  assert(k != NULL, "invariant");
-  PkgPtr pkg = k->package();
-  if (pkg != NULL) {
-    tag_leakp_artifact(pkg, class_unload);
-    ModPtr module = pkg->module();
-    if (module != NULL) {
-      tag_leakp_artifact(module, class_unload);
-    }
+static traceid package_id(KlassPtr klass, bool leakp) {
+  assert(klass != NULL, "invariant");
+  PkgPtr pkg_entry = klass->package();
+  if (pkg_entry == NULL) {
+    return 0;
+  }
+  if (leakp) {
+    SET_LEAKP(pkg_entry);
   }
-  CldPtr cld = k->class_loader_data();
-  assert(cld != NULL, "invariant");
-  if (!cld->is_unsafe_anonymous()) {
-    tag_leakp_artifact(cld, class_unload);
+  // package implicitly tagged already
+  return artifact_id(pkg_entry);
+}
+
+static traceid module_id(PkgPtr pkg, bool leakp) {
+  assert(pkg != NULL, "invariant");
+  ModPtr module_entry = pkg->module();
+  if (module_entry == NULL || !module_entry->is_named()) {
+    return 0;
   }
+  if (leakp) {
+    SET_LEAKP(module_entry);
+  } else {
+    SET_TRANSIENT(module_entry);
+  }
+  return artifact_id(module_entry);
 }
 
-class TagLeakpKlassArtifact {
-  bool _class_unload;
- public:
-  TagLeakpKlassArtifact(bool class_unload) : _class_unload(class_unload) {}
-  bool operator()(KlassPtr klass) {
-    if (_class_unload) {
-      if (LEAKP_USED_THIS_EPOCH(klass)) {
-        tag_leakp_klass_artifacts(klass, _class_unload);
-      }
-    } else {
-      if (LEAKP_USED_PREV_EPOCH(klass)) {
-        tag_leakp_klass_artifacts(klass, _class_unload);
-      }
-    }
-    return true;
+static traceid method_id(KlassPtr klass, MethodPtr method) {
+  assert(klass != NULL, "invariant");
+  assert(method != NULL, "invariant");
+  return METHOD_ID(klass, method);
+}
+
+static traceid cld_id(CldPtr cld, bool leakp) {
+  assert(cld != NULL, "invariant");
+  if (cld->is_unsafe_anonymous()) {
+    return 0;
+  }
+  if (leakp) {
+    SET_LEAKP(cld);
+  } else {
+    SET_TRANSIENT(cld);
   }
-};
+  return artifact_id(cld);
+}
+
+template <typename T>
+static s4 get_flags(const T* ptr) {
+  assert(ptr != NULL, "invariant");
+  return ptr->access_flags().get_flags();
+}
+
+template <typename T>
+static void set_serialized(const T* ptr) {
+  assert(ptr != NULL, "invariant");
+  SET_SERIALIZED(ptr);
+  assert(IS_SERIALIZED(ptr), "invariant");
+}
 
 /*
  * In C++03, functions used as template parameters must have external linkage;
@@ -123,11 +168,10 @@
  * The weird naming is an effort to decrease the risk of name clashes.
  */
 
-int write__artifact__klass(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
+static int write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp) {
   assert(writer != NULL, "invariant");
-  assert(artifacts != NULL, "invariant");
-  assert(k != NULL, "invariant");
-  KlassPtr klass = (KlassPtr)k;
+  assert(_artifacts != NULL, "invariant");
+  assert(klass != NULL, "invariant");
   traceid pkg_id = 0;
   KlassPtr theklass = klass;
   if (theklass->is_objArray_klass()) {
@@ -135,445 +179,167 @@
     theklass = obj_arr_klass->bottom_klass();
   }
   if (theklass->is_instance_klass()) {
-    pkg_id = package_id(theklass);
+    pkg_id = package_id(theklass, leakp);
   } else {
     assert(theklass->is_typeArray_klass(), "invariant");
   }
-  const traceid symbol_id = artifacts->mark(klass);
-  assert(symbol_id > 0, "need to have an address for symbol!");
-  writer->write(TRACE_ID(klass));
-  writer->write(cld_id(klass->class_loader_data()));
-  writer->write((traceid)CREATE_SYMBOL_ID(symbol_id));
+  writer->write(artifact_id(klass));
+  writer->write(cld_id(klass->class_loader_data(), leakp));
+  writer->write(mark_symbol(klass, leakp));
   writer->write(pkg_id);
-  writer->write((s4)klass->access_flags().get_flags());
+  writer->write(get_flags(klass));
   return 1;
 }
 
-typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
-typedef JfrPredicatedArtifactWriterImplHost<KlassPtr, LeakKlassPredicate, write__artifact__klass> LeakKlassWriterImpl;
-typedef JfrArtifactWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
-typedef JfrArtifactWriterImplHost<KlassPtr, write__artifact__klass> KlassWriterImpl;
-typedef JfrArtifactWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
+int write__klass(JfrCheckpointWriter* writer, const void* k) {
+  assert(k != NULL, "invariant");
+  KlassPtr klass = (KlassPtr)k;
+  set_serialized(klass);
+  return write_klass(writer, klass, false);
+}
+
+int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) {
+  assert(k != NULL, "invariant");
+  KlassPtr klass = (KlassPtr)k;
+  return write_klass(writer, klass, true);
+}
+
+static void do_implied(Klass* klass) {
+  assert(klass != NULL, "invariant");
+  if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
+    if (_leakp_writer != NULL) {
+      SET_LEAKP(klass);
+    }
+    _subsystem_callback->do_artifact(klass);
+  }
+}
 
-int write__artifact__method(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
-  assert(writer != NULL, "invariant");
-  assert(artifacts != NULL, "invariant");
-  assert(m != NULL, "invariant");
-  MethodPtr method = (MethodPtr)m;
-  const traceid method_name_symbol_id = artifacts->mark(method->name());
-  assert(method_name_symbol_id > 0, "invariant");
-  const traceid method_sig_symbol_id = artifacts->mark(method->signature());
-  assert(method_sig_symbol_id > 0, "invariant");
-  KlassPtr klass = method->method_holder();
+static void do_unloaded_klass(Klass* klass) {
+  assert(klass != NULL, "invariant");
+  assert(_subsystem_callback != NULL, "invariant");
+  if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) {
+    JfrEventClasses::increment_unloaded_event_class();
+  }
+  if (USED_THIS_EPOCH(klass)) {
+    ObjectSampleCheckpoint::on_klass_unload(klass);
+    _subsystem_callback->do_artifact(klass);
+    return;
+  }
+  do_implied(klass);
+}
+
+static void do_klass(Klass* klass) {
   assert(klass != NULL, "invariant");
-  assert(METHOD_USED_ANY_EPOCH(klass), "invariant");
-  writer->write((u8)METHOD_ID(klass, method));
-  writer->write((u8)TRACE_ID(klass));
-  writer->write((u8)CREATE_SYMBOL_ID(method_name_symbol_id));
-  writer->write((u8)CREATE_SYMBOL_ID(method_sig_symbol_id));
-  writer->write((u2)method->access_flags().get_flags());
-  writer->write(const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0);
-  return 1;
+  assert(_subsystem_callback != NULL, "invariant");
+  if (current_epoch()) {
+    if (USED_THIS_EPOCH(klass)) {
+      _subsystem_callback->do_artifact(klass);
+      return;
+    }
+  } else {
+    if (USED_PREV_EPOCH(klass)) {
+      _subsystem_callback->do_artifact(klass);
+      return;
+    }
+  }
+  do_implied(klass);
+}
+
+static void do_klasses() {
+  if (_class_unload) {
+    ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass);
+    return;
+  }
+  ClassLoaderDataGraph::classes_do(&do_klass);
 }
 
-typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget;
-typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
+typedef SerializePredicate<KlassPtr> KlassPredicate;
+typedef JfrPredicatedTypeWriterImplHost<KlassPtr, KlassPredicate, write__klass> KlassWriterImpl;
+typedef JfrTypeWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
+typedef CompositeFunctor<KlassPtr, KlassWriter, KlassArtifactRegistrator> KlassWriterRegistration;
+typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
+
+typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
+typedef JfrPredicatedTypeWriterImplHost<KlassPtr, LeakKlassPredicate, write__klass__leakp> LeakKlassWriterImpl;
+typedef JfrTypeWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
+
+typedef CompositeFunctor<KlassPtr, LeakKlassWriter, KlassWriter> CompositeKlassWriter;
+typedef CompositeFunctor<KlassPtr, CompositeKlassWriter, KlassArtifactRegistrator> CompositeKlassWriterRegistration;
+typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
 
-int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) {
+static bool write_klasses() {
+  assert(!_artifacts->has_klass_entries(), "invariant");
+  assert(_writer != NULL, "invariant");
+  KlassArtifactRegistrator reg(_artifacts);
+  KlassWriter kw(_writer, _class_unload);
+  KlassWriterRegistration kwr(&kw, &reg);
+  if (_leakp_writer == NULL) {
+    KlassCallback callback(&kwr);
+    _subsystem_callback = &callback;
+    do_klasses();
+  } else {
+    LeakKlassWriter lkw(_leakp_writer, _artifacts, _class_unload);
+    CompositeKlassWriter ckw(&lkw, &kw);
+    CompositeKlassWriterRegistration ckwr(&ckw, &reg);
+    CompositeKlassCallback callback(&ckwr);
+    _subsystem_callback = &callback;
+    do_klasses();
+  }
+  if (is_complete()) {
+    return false;
+  }
+  _artifacts->tally(kw);
+  return true;
+}
+
+template <typename T>
+static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) {
+  assert(callback != NULL, "invariant");
+  assert(value != NULL, "invariant");
+  if (USED_PREV_EPOCH(value)) {
+    callback->do_artifact(value);
+    assert(IS_NOT_SERIALIZED(value), "invariant");
+    return;
+  }
+  if (IS_SERIALIZED(value)) {
+    CLEAR_SERIALIZED(value);
+  }
+  assert(IS_NOT_SERIALIZED(value), "invariant");
+}
+
+static int write_package(JfrCheckpointWriter* writer, PkgPtr pkg, bool leakp) {
   assert(writer != NULL, "invariant");
-  assert(artifacts != NULL, "invariant");
-  assert(p != NULL, "invariant");
-  PkgPtr pkg = (PkgPtr)p;
-  Symbol* const pkg_name = pkg->name();
-  const traceid package_name_symbol_id = pkg_name != NULL ? artifacts->mark(pkg_name) : 0;
-  assert(package_name_symbol_id > 0, "invariant");
-  writer->write((traceid)TRACE_ID(pkg));
-  writer->write((traceid)CREATE_SYMBOL_ID(package_name_symbol_id));
-  writer->write(module_id(pkg));
+  assert(_artifacts != NULL, "invariant");
+  assert(pkg != NULL, "invariant");
+  writer->write(artifact_id(pkg));
+  writer->write(mark_symbol(pkg->name(), leakp));
+  writer->write(module_id(pkg, leakp));
   writer->write((bool)pkg->is_exported());
   return 1;
 }
 
-typedef LeakPredicate<PkgPtr> LeakPackagePredicate;
-int _compare_pkg_ptr_(PkgPtr const& lhs, PkgPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
-typedef UniquePredicate<PkgPtr, _compare_pkg_ptr_> PackagePredicate;
-typedef JfrPredicatedArtifactWriterImplHost<PkgPtr, LeakPackagePredicate, write__artifact__package> LeakPackageWriterImpl;
-typedef JfrPredicatedArtifactWriterImplHost<PkgPtr, PackagePredicate, write__artifact__package> PackageWriterImpl;
-typedef JfrArtifactWriterHost<LeakPackageWriterImpl, TYPE_PACKAGE> LeakPackageWriter;
-typedef JfrArtifactWriterHost<PackageWriterImpl, TYPE_PACKAGE> PackageWriter;
-
-int write__artifact__module(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
-  assert( m != NULL, "invariant");
-  ModPtr entry = (ModPtr)m;
-  Symbol* const module_name = entry->name();
-  const traceid module_name_symbol_id = module_name != NULL ? artifacts->mark(module_name) : 0;
-  Symbol* const module_version = entry->version();
-  const traceid module_version_symbol_id = module_version != NULL ? artifacts->mark(module_version) : 0;
-  Symbol* const module_location = entry->location();
-  const traceid module_location_symbol_id = module_location != NULL ? artifacts->mark(module_location) : 0;
-  writer->write((traceid)TRACE_ID(entry));
-  writer->write(module_name_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_name_symbol_id));
-  writer->write(module_version_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_version_symbol_id));
-  writer->write(module_location_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_location_symbol_id));
-  writer->write(cld_id(entry->loader_data()));
-  return 1;
-}
-
-typedef LeakPredicate<ModPtr> LeakModulePredicate;
-int _compare_mod_ptr_(ModPtr const& lhs, ModPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
-typedef UniquePredicate<ModPtr, _compare_mod_ptr_> ModulePredicate;
-typedef JfrPredicatedArtifactWriterImplHost<ModPtr, LeakModulePredicate, write__artifact__module> LeakModuleWriterImpl;
-typedef JfrPredicatedArtifactWriterImplHost<ModPtr, ModulePredicate, write__artifact__module> ModuleWriterImpl;
-typedef JfrArtifactWriterHost<LeakModuleWriterImpl, TYPE_MODULE> LeakModuleWriter;
-typedef JfrArtifactWriterHost<ModuleWriterImpl, TYPE_MODULE> ModuleWriter;
-
-int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) {
-  assert(c != NULL, "invariant");
-  CldPtr cld = (CldPtr)c;
-  assert(!cld->is_unsafe_anonymous(), "invariant");
-  const traceid cld_id = TRACE_ID(cld);
-  // class loader type
-  const Klass* class_loader_klass = cld->class_loader_klass();
-  if (class_loader_klass == NULL) {
-    // (primordial) boot class loader
-    writer->write(cld_id); // class loader instance id
-    writer->write((traceid)0);  // class loader type id (absence of)
-    writer->write((traceid)CREATE_SYMBOL_ID(1)); // 1 maps to synthetic name -> "bootstrap"
-  } else {
-    Symbol* symbol_name = cld->name();
-    const traceid symbol_name_id = symbol_name != NULL ? artifacts->mark(symbol_name) : 0;
-    writer->write(cld_id); // class loader instance id
-    writer->write(TRACE_ID(class_loader_klass)); // class loader type id
-    writer->write(symbol_name_id == 0 ? (traceid)0 :
-      (traceid)CREATE_SYMBOL_ID(symbol_name_id)); // class loader instance name
-  }
-  return 1;
-}
-
-typedef LeakPredicate<CldPtr> LeakCldPredicate;
-int _compare_cld_ptr_(CldPtr const& lhs, CldPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
-typedef UniquePredicate<CldPtr, _compare_cld_ptr_> CldPredicate;
-typedef JfrPredicatedArtifactWriterImplHost<CldPtr, LeakCldPredicate, write__artifact__classloader> LeakCldWriterImpl;
-typedef JfrPredicatedArtifactWriterImplHost<CldPtr, CldPredicate, write__artifact__classloader> CldWriterImpl;
-typedef JfrArtifactWriterHost<LeakCldWriterImpl, TYPE_CLASSLOADER> LeakCldWriter;
-typedef JfrArtifactWriterHost<CldWriterImpl, TYPE_CLASSLOADER> CldWriter;
-
-typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
-
-static int write__artifact__symbol__entry__(JfrCheckpointWriter* writer,
-                                            SymbolEntryPtr entry) {
-  assert(writer != NULL, "invariant");
-  assert(entry != NULL, "invariant");
-  ResourceMark rm;
-  writer->write(CREATE_SYMBOL_ID(entry->id()));
-  writer->write(entry->value()->as_C_string());
-  return 1;
-}
-
-int write__artifact__symbol__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
-  assert(e != NULL, "invariant");
-  return write__artifact__symbol__entry__(writer, (SymbolEntryPtr)e);
-}
-
-typedef JfrArtifactWriterImplHost<SymbolEntryPtr, write__artifact__symbol__entry> SymbolEntryWriterImpl;
-typedef JfrArtifactWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
-
-typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
-
-static int write__artifact__cstring__entry__(JfrCheckpointWriter* writer, CStringEntryPtr entry) {
-  assert(writer != NULL, "invariant");
-  assert(entry != NULL, "invariant");
-  writer->write(CREATE_SYMBOL_ID(entry->id()));
-  writer->write(entry->value());
-  return 1;
-}
-
-int write__artifact__cstring__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
-  assert(e != NULL, "invariant");
-  return write__artifact__cstring__entry__(writer, (CStringEntryPtr)e);
-}
-
-typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__cstring__entry> CStringEntryWriterImpl;
-typedef JfrArtifactWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
-
-int write__artifact__klass__symbol(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
-  assert(writer != NULL, "invariant");
-  assert(artifacts != NULL, "invaiant");
-  assert(k != NULL, "invariant");
-  const InstanceKlass* const ik = (const InstanceKlass*)k;
-  if (ik->is_unsafe_anonymous()) {
-    CStringEntryPtr entry =
-      artifacts->map_cstring(JfrSymbolId::unsafe_anonymous_klass_name_hash_code(ik));
-    assert(entry != NULL, "invariant");
-    return write__artifact__cstring__entry__(writer, entry);
-  }
-
-  SymbolEntryPtr entry = artifacts->map_symbol(JfrSymbolId::regular_klass_name_hash_code(ik));
-  return write__artifact__symbol__entry__(writer, entry);
-}
-
-int _compare_traceid_(const traceid& lhs, const traceid& rhs) {
-  return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
+int write__package(JfrCheckpointWriter* writer, const void* p) {
+  assert(p != NULL, "invariant");
+  PkgPtr pkg = (PkgPtr)p;
+  set_serialized(pkg);
+  return write_package(writer, pkg, false);
 }
 
-template <template <typename> class Predicate>
-class KlassSymbolWriterImpl {
- private:
-  JfrCheckpointWriter* _writer;
-  JfrArtifactSet* _artifacts;
-  Predicate<KlassPtr> _predicate;
-  MethodUsedPredicate<true> _method_used_predicate;
-  MethodFlagPredicate _method_flag_predicate;
-  UniquePredicate<traceid, _compare_traceid_> _unique_predicate;
-
-  int klass_symbols(KlassPtr klass);
-  int package_symbols(PkgPtr pkg);
-  int module_symbols(ModPtr module);
-  int class_loader_symbols(CldPtr cld);
-  int method_symbols(KlassPtr klass);
-
- public:
-  typedef KlassPtr Type;
-  KlassSymbolWriterImpl(JfrCheckpointWriter* writer,
-                        JfrArtifactSet* artifacts,
-                        bool class_unload) : _writer(writer),
-                                             _artifacts(artifacts),
-                                             _predicate(class_unload),
-                                             _method_used_predicate(class_unload),
-                                             _method_flag_predicate(class_unload),
-                                             _unique_predicate(class_unload) {}
-
-  int operator()(KlassPtr klass) {
-    assert(klass != NULL, "invariant");
-    int count = 0;
-    if (_predicate(klass)) {
-      count += klass_symbols(klass);
-      PkgPtr pkg = klass->package();
-      if (pkg != NULL) {
-        count += package_symbols(pkg);
-        ModPtr module = pkg->module();
-        if (module != NULL && module->is_named()) {
-          count += module_symbols(module);
-        }
-      }
-      CldPtr cld = klass->class_loader_data();
-      assert(cld != NULL, "invariant");
-      if (!cld->is_unsafe_anonymous()) {
-        count += class_loader_symbols(cld);
-      }
-      if (_method_used_predicate(klass)) {
-        count += method_symbols(klass);
-      }
-    }
-    return count;
-  }
-};
-
-template <template <typename> class Predicate>
-int KlassSymbolWriterImpl<Predicate>::klass_symbols(KlassPtr klass) {
-  assert(klass != NULL, "invariant");
-  assert(_predicate(klass), "invariant");
-  const InstanceKlass* const ik = (const InstanceKlass*)klass;
-  if (ik->is_unsafe_anonymous()) {
-    CStringEntryPtr entry =
-      this->_artifacts->map_cstring(JfrSymbolId::unsafe_anonymous_klass_name_hash_code(ik));
-    assert(entry != NULL, "invariant");
-    return _unique_predicate(entry->id()) ? write__artifact__cstring__entry__(this->_writer, entry) : 0;
-  }
-  SymbolEntryPtr entry = this->_artifacts->map_symbol(ik->name());
-  assert(entry != NULL, "invariant");
-  return _unique_predicate(entry->id()) ? write__artifact__symbol__entry__(this->_writer, entry) : 0;
-}
-
-template <template <typename> class Predicate>
-int KlassSymbolWriterImpl<Predicate>::package_symbols(PkgPtr pkg) {
-  assert(pkg != NULL, "invariant");
-  SymbolPtr pkg_name = pkg->name();
-  assert(pkg_name != NULL, "invariant");
-  SymbolEntryPtr package_symbol = this->_artifacts->map_symbol(pkg_name);
-  assert(package_symbol != NULL, "invariant");
-  return _unique_predicate(package_symbol->id()) ?
-    write__artifact__symbol__entry__(this->_writer, package_symbol) : 0;
-}
-
-template <template <typename> class Predicate>
-int KlassSymbolWriterImpl<Predicate>::module_symbols(ModPtr module) {
-  assert(module != NULL, "invariant");
-  assert(module->is_named(), "invariant");
-  int count = 0;
-  SymbolPtr sym = module->name();
-  SymbolEntryPtr entry = NULL;
-  if (sym != NULL) {
-    entry = this->_artifacts->map_symbol(sym);
-    assert(entry != NULL, "invariant");
-    if (_unique_predicate(entry->id())) {
-      count += write__artifact__symbol__entry__(this->_writer, entry);
-    }
-  }
-  sym = module->version();
-  if (sym != NULL) {
-    entry = this->_artifacts->map_symbol(sym);
-    assert(entry != NULL, "invariant");
-    if (_unique_predicate(entry->id())) {
-      count += write__artifact__symbol__entry__(this->_writer, entry);
-    }
-  }
-  sym = module->location();
-  if (sym != NULL) {
-    entry = this->_artifacts->map_symbol(sym);
-    assert(entry != NULL, "invariant");
-    if (_unique_predicate(entry->id())) {
-      count += write__artifact__symbol__entry__(this->_writer, entry);
-    }
-  }
-  return count;
+int write__package__leakp(JfrCheckpointWriter* writer, const void* p) {
+  assert(p != NULL, "invariant");
+  PkgPtr pkg = (PkgPtr)p;
+  CLEAR_LEAKP(pkg);
+  return write_package(writer, pkg, true);
 }
 
-template <template <typename> class Predicate>
-int KlassSymbolWriterImpl<Predicate>::class_loader_symbols(CldPtr cld) {
-  assert(cld != NULL, "invariant");
-  assert(!cld->is_unsafe_anonymous(), "invariant");
-  int count = 0;
-  // class loader type
-  const Klass* class_loader_klass = cld->class_loader_klass();
-  if (class_loader_klass == NULL) {
-    // (primordial) boot class loader
-    CStringEntryPtr entry = this->_artifacts->map_cstring(0);
-    assert(entry != NULL, "invariant");
-    assert(strncmp(entry->literal(),
-      BOOTSTRAP_LOADER_NAME,
-      BOOTSTRAP_LOADER_NAME_LEN) == 0, "invariant");
-    if (_unique_predicate(entry->id())) {
-      count += write__artifact__cstring__entry__(this->_writer, entry);
-    }
-  } else {
-    const Symbol* class_loader_name = cld->name();
-    if (class_loader_name != NULL) {
-      SymbolEntryPtr entry = this->_artifacts->map_symbol(class_loader_name);
-      assert(entry != NULL, "invariant");
-      if (_unique_predicate(entry->id())) {
-        count += write__artifact__symbol__entry__(this->_writer, entry);
-      }
-    }
-  }
-  return count;
-}
-
-template <template <typename> class Predicate>
-int KlassSymbolWriterImpl<Predicate>::method_symbols(KlassPtr klass) {
-  assert(_predicate(klass), "invariant");
-  assert(_method_used_predicate(klass), "invariant");
-  assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
-  int count = 0;
-  const InstanceKlass* const ik = InstanceKlass::cast(klass);
-  const int len = ik->methods()->length();
-  for (int i = 0; i < len; ++i) {
-    MethodPtr method = ik->methods()->at(i);
-    if (_method_flag_predicate(method)) {
-      SymbolEntryPtr entry = this->_artifacts->map_symbol(method->name());
-      assert(entry != NULL, "invariant");
-      if (_unique_predicate(entry->id())) {
-        count += write__artifact__symbol__entry__(this->_writer, entry);
-      }
-      entry = this->_artifacts->map_symbol(method->signature());
-      assert(entry != NULL, "invariant");
-      if (_unique_predicate(entry->id())) {
-        count += write__artifact__symbol__entry__(this->_writer, entry);
-      }
-    }
-  }
-  return count;
+static void do_package(PackageEntry* entry) {
+  do_previous_epoch_artifact(_subsystem_callback, entry);
 }
 
-typedef KlassSymbolWriterImpl<LeakPredicate> LeakKlassSymbolWriterImpl;
-typedef JfrArtifactWriterHost<LeakKlassSymbolWriterImpl, TYPE_SYMBOL> LeakKlassSymbolWriter;
-
-class ClearKlassAndMethods {
- private:
-  ClearArtifact<KlassPtr> _clear_klass_tag_bits;
-  ClearArtifact<MethodPtr> _clear_method_flag;
-  MethodUsedPredicate<false> _method_used_predicate;
-
- public:
-  ClearKlassAndMethods(bool class_unload) : _clear_klass_tag_bits(class_unload),
-                                            _clear_method_flag(class_unload),
-                                            _method_used_predicate(class_unload) {}
-  bool operator()(KlassPtr klass) {
-    if (_method_used_predicate(klass)) {
-      const InstanceKlass* ik = InstanceKlass::cast(klass);
-      const int len = ik->methods()->length();
-      for (int i = 0; i < len; ++i) {
-        MethodPtr method = ik->methods()->at(i);
-        _clear_method_flag(method);
-      }
-    }
-    _clear_klass_tag_bits(klass);
-    return true;
-  }
-};
-
-typedef CompositeFunctor<KlassPtr,
-                         TagLeakpKlassArtifact,
-                         LeakKlassWriter> LeakpKlassArtifactTagging;
-
-typedef CompositeFunctor<KlassPtr,
-                         LeakpKlassArtifactTagging,
-                         KlassWriter> CompositeKlassWriter;
-
-typedef CompositeFunctor<KlassPtr,
-                         CompositeKlassWriter,
-                         KlassArtifactRegistrator> CompositeKlassWriterRegistration;
-
-typedef CompositeFunctor<KlassPtr,
-                         KlassWriter,
-                         KlassArtifactRegistrator> KlassWriterRegistration;
-
-typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
-typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
-
-/*
- * Composite operation
- *
- * TagLeakpKlassArtifact ->
- *   LeakpPredicate ->
- *     LeakpKlassWriter ->
- *       KlassPredicate ->
- *         KlassWriter ->
- *           KlassWriterRegistration
- */
-void JfrTypeSet::write_klass_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
-  assert(!_artifacts->has_klass_entries(), "invariant");
-  KlassArtifactRegistrator reg(_artifacts);
-  KlassWriter kw(writer, _artifacts, _class_unload);
-  KlassWriterRegistration kwr(&kw, &reg);
-  if (leakp_writer == NULL) {
-    KlassCallback callback(&kwr);
-    _subsystem_callback = &callback;
-    do_klasses();
-    return;
-  }
-  TagLeakpKlassArtifact tagging(_class_unload);
-  LeakKlassWriter lkw(leakp_writer, _artifacts, _class_unload);
-  LeakpKlassArtifactTagging lpkat(&tagging, &lkw);
-  CompositeKlassWriter ckw(&lpkat, &kw);
-  CompositeKlassWriterRegistration ckwr(&ckw, &reg);
-  CompositeKlassCallback callback(&ckwr);
-  _subsystem_callback = &callback;
-  do_klasses();
+static void do_packages() {
+  ClassLoaderDataGraph::packages_do(&do_package);
 }
 
-typedef CompositeFunctor<PkgPtr,
-                         PackageWriter,
-                         ClearArtifact<PkgPtr> > PackageWriterWithClear;
-
-typedef CompositeFunctor<PkgPtr,
-                         LeakPackageWriter,
-                         PackageWriter> CompositePackageWriter;
-
-typedef CompositeFunctor<PkgPtr,
-                         CompositePackageWriter,
-                         ClearArtifact<PkgPtr> > CompositePackageWriterWithClear;
-
 class PackageFieldSelector {
  public:
   typedef PkgPtr TypePtr;
@@ -583,60 +349,86 @@
   }
 };
 
-typedef KlassToFieldEnvelope<PackageFieldSelector,
-                             PackageWriterWithClear> KlassPackageWriterWithClear;
+typedef SerializePredicate<PkgPtr> PackagePredicate;
+typedef JfrPredicatedTypeWriterImplHost<PkgPtr, PackagePredicate, write__package> PackageWriterImpl;
+typedef JfrTypeWriterHost<PackageWriterImpl, TYPE_PACKAGE> PackageWriter;
+typedef CompositeFunctor<PkgPtr, PackageWriter, ClearArtifact<PkgPtr> > PackageWriterWithClear;
+typedef KlassToFieldEnvelope<PackageFieldSelector, PackageWriter> KlassPackageWriter;
+typedef JfrArtifactCallbackHost<PkgPtr, PackageWriterWithClear> PackageCallback;
 
-typedef KlassToFieldEnvelope<PackageFieldSelector,
-                             CompositePackageWriterWithClear> KlassCompositePackageWriterWithClear;
+typedef LeakPredicate<PkgPtr> LeakPackagePredicate;
+typedef JfrPredicatedTypeWriterImplHost<PkgPtr, LeakPackagePredicate, write__package__leakp> LeakPackageWriterImpl;
+typedef JfrTypeWriterHost<LeakPackageWriterImpl, TYPE_PACKAGE> LeakPackageWriter;
 
-typedef JfrArtifactCallbackHost<PkgPtr, PackageWriterWithClear> PackageCallback;
+typedef CompositeFunctor<PkgPtr, LeakPackageWriter, PackageWriter> CompositePackageWriter;
+typedef KlassToFieldEnvelope<PackageFieldSelector, CompositePackageWriter> KlassCompositePackageWriter;
+typedef KlassToFieldEnvelope<PackageFieldSelector, PackageWriterWithClear> KlassPackageWriterWithClear;
+typedef CompositeFunctor<PkgPtr, CompositePackageWriter, ClearArtifact<PkgPtr> > CompositePackageWriterWithClear;
 typedef JfrArtifactCallbackHost<PkgPtr, CompositePackageWriterWithClear> CompositePackageCallback;
 
-/*
- * Composite operation
- *
- * LeakpPackageWriter ->
- *   PackageWriter ->
- *     ClearArtifact<PackageEntry>
- *
- */
-void JfrTypeSet::write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
-  assert(_artifacts->has_klass_entries(), "invariant");
-  ClearArtifact<PkgPtr> clear(_class_unload);
-  PackageWriter pw(writer, _artifacts, _class_unload);
-  if (leakp_writer == NULL) {
+static void write_packages() {
+  assert(_writer != NULL, "invariant");
+  PackageWriter pw(_writer, _class_unload);
+  KlassPackageWriter kpw(&pw);
+  if (current_epoch()) {
+    _artifacts->iterate_klasses(kpw);
+    _artifacts->tally(pw);
+    return;
+  }
+  assert(previous_epoch(), "invariant");
+  if (_leakp_writer == NULL) {
+    _artifacts->iterate_klasses(kpw);
+    ClearArtifact<PkgPtr> clear;
     PackageWriterWithClear pwwc(&pw, &clear);
-    KlassPackageWriterWithClear kpwwc(&pwwc);
-    _artifacts->iterate_klasses(kpwwc);
     PackageCallback callback(&pwwc);
     _subsystem_callback = &callback;
     do_packages();
-    return;
+  } else {
+    LeakPackageWriter lpw(_leakp_writer, _class_unload);
+    CompositePackageWriter cpw(&lpw, &pw);
+    KlassCompositePackageWriter kcpw(&cpw);
+    _artifacts->iterate_klasses(kcpw);
+    ClearArtifact<PkgPtr> clear;
+    CompositePackageWriterWithClear cpwwc(&cpw, &clear);
+    CompositePackageCallback callback(&cpwwc);
+    _subsystem_callback = &callback;
+    do_packages();
   }
-  LeakPackageWriter lpw(leakp_writer, _artifacts, _class_unload);
-  CompositePackageWriter cpw(&lpw, &pw);
-  CompositePackageWriterWithClear cpwwc(&cpw, &clear);
-  KlassCompositePackageWriterWithClear ckpw(&cpwwc);
-  _artifacts->iterate_klasses(ckpw);
-  CompositePackageCallback callback(&cpwwc);
-  _subsystem_callback = &callback;
-  do_packages();
+  _artifacts->tally(pw);
 }
 
-typedef CompositeFunctor<ModPtr,
-                         ModuleWriter,
-                         ClearArtifact<ModPtr> > ModuleWriterWithClear;
+static int write_module(JfrCheckpointWriter* writer, ModPtr mod, bool leakp) {
+  assert(mod != NULL, "invariant");
+  assert(_artifacts != NULL, "invariant");
+  writer->write(artifact_id(mod));
+  writer->write(mark_symbol(mod->name(), leakp));
+  writer->write(mark_symbol(mod->version(), leakp));
+  writer->write(mark_symbol(mod->location(), leakp));
+  writer->write(cld_id(mod->loader_data(), leakp));
+  return 1;
+}
 
-typedef CompositeFunctor<ModPtr,
-                         LeakModuleWriter,
-                         ModuleWriter> CompositeModuleWriter;
+int write__module(JfrCheckpointWriter* writer, const void* m) {
+  assert(m != NULL, "invariant");
+  ModPtr mod = (ModPtr)m;
+  set_serialized(mod);
+  return write_module(writer, mod, false);
+}
 
-typedef CompositeFunctor<ModPtr,
-                         CompositeModuleWriter,
-                         ClearArtifact<ModPtr> > CompositeModuleWriterWithClear;
+int write__module__leakp(JfrCheckpointWriter* writer, const void* m) {
+  assert(m != NULL, "invariant");
+  ModPtr mod = (ModPtr)m;
+  CLEAR_LEAKP(mod);
+  return write_module(writer, mod, true);
+}
 
-typedef JfrArtifactCallbackHost<ModPtr, ModuleWriterWithClear> ModuleCallback;
-typedef JfrArtifactCallbackHost<ModPtr, CompositeModuleWriterWithClear> CompositeModuleCallback;
+static void do_module(ModuleEntry* entry) {
+  do_previous_epoch_artifact(_subsystem_callback, entry);
+}
+
+static void do_modules() {
+  ClassLoaderDataGraph::modules_do(&do_module);
+}
 
 class ModuleFieldSelector {
  public:
@@ -648,47 +440,88 @@
   }
 };
 
-typedef KlassToFieldEnvelope<ModuleFieldSelector,
-                             ModuleWriterWithClear> KlassModuleWriterWithClear;
+typedef SerializePredicate<ModPtr> ModulePredicate;
+typedef JfrPredicatedTypeWriterImplHost<ModPtr, ModulePredicate, write__module> ModuleWriterImpl;
+typedef JfrTypeWriterHost<ModuleWriterImpl, TYPE_MODULE> ModuleWriter;
+typedef CompositeFunctor<ModPtr, ModuleWriter, ClearArtifact<ModPtr> > ModuleWriterWithClear;
+typedef JfrArtifactCallbackHost<ModPtr, ModuleWriterWithClear> ModuleCallback;
+typedef KlassToFieldEnvelope<ModuleFieldSelector, ModuleWriter> KlassModuleWriter;
 
-typedef KlassToFieldEnvelope<ModuleFieldSelector,
-                             CompositeModuleWriterWithClear> KlassCompositeModuleWriterWithClear;
+typedef LeakPredicate<ModPtr> LeakModulePredicate;
+typedef JfrPredicatedTypeWriterImplHost<ModPtr, LeakModulePredicate, write__module__leakp> LeakModuleWriterImpl;
+typedef JfrTypeWriterHost<LeakModuleWriterImpl, TYPE_MODULE> LeakModuleWriter;
 
-/*
- * Composite operation
- *
- * LeakpModuleWriter ->
- *   ModuleWriter ->
- *     ClearArtifact<ModuleEntry>
- */
-void JfrTypeSet::write_module_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
-  assert(_artifacts->has_klass_entries(), "invariant");
-  ClearArtifact<ModPtr> clear(_class_unload);
-  ModuleWriter mw(writer, _artifacts, _class_unload);
-  if (leakp_writer == NULL) {
+typedef CompositeFunctor<ModPtr, LeakModuleWriter, ModuleWriter> CompositeModuleWriter;
+typedef KlassToFieldEnvelope<ModuleFieldSelector, CompositeModuleWriter> KlassCompositeModuleWriter;
+typedef CompositeFunctor<ModPtr, CompositeModuleWriter, ClearArtifact<ModPtr> > CompositeModuleWriterWithClear;
+typedef JfrArtifactCallbackHost<ModPtr, CompositeModuleWriterWithClear> CompositeModuleCallback;
+
+static void write_modules() {
+  assert(_writer != NULL, "invariant");
+  ModuleWriter mw(_writer, _class_unload);
+  KlassModuleWriter kmw(&mw);
+  if (current_epoch()) {
+    _artifacts->iterate_klasses(kmw);
+    _artifacts->tally(mw);
+    return;
+  }
+  assert(previous_epoch(), "invariant");
+  if (_leakp_writer == NULL) {
+    _artifacts->iterate_klasses(kmw);
+    ClearArtifact<ModPtr> clear;
     ModuleWriterWithClear mwwc(&mw, &clear);
-    KlassModuleWriterWithClear kmwwc(&mwwc);
-    _artifacts->iterate_klasses(kmwwc);
     ModuleCallback callback(&mwwc);
     _subsystem_callback = &callback;
     do_modules();
-    return;
+  } else {
+    LeakModuleWriter lmw(_leakp_writer, _class_unload);
+    CompositeModuleWriter cmw(&lmw, &mw);
+    KlassCompositeModuleWriter kcpw(&cmw);
+    _artifacts->iterate_klasses(kcpw);
+    ClearArtifact<ModPtr> clear;
+    CompositeModuleWriterWithClear cmwwc(&cmw, &clear);
+    CompositeModuleCallback callback(&cmwwc);
+    _subsystem_callback = &callback;
+    do_modules();
   }
-  LeakModuleWriter lmw(leakp_writer, _artifacts, _class_unload);
-  CompositeModuleWriter cmw(&lmw, &mw);
-  CompositeModuleWriterWithClear cmwwc(&cmw, &clear);
-  KlassCompositeModuleWriterWithClear kmwwc(&cmwwc);
-  _artifacts->iterate_klasses(kmwwc);
-  CompositeModuleCallback callback(&cmwwc);
-  _subsystem_callback = &callback;
-  do_modules();
+  _artifacts->tally(mw);
 }
 
-typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
-typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
-typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
-typedef JfrArtifactCallbackHost<CldPtr, CldWriterWithClear> CldCallback;
-typedef JfrArtifactCallbackHost<CldPtr, CompositeCldWriterWithClear> CompositeCldCallback;
+static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) {
+  assert(cld != NULL, "invariant");
+  assert(!cld->is_unsafe_anonymous(), "invariant");
+  // class loader type
+  const Klass* class_loader_klass = cld->class_loader_klass();
+  if (class_loader_klass == NULL) {
+    // (primordial) boot class loader
+    writer->write(artifact_id(cld)); // class loader instance id
+    writer->write((traceid)0);  // class loader type id (absence of)
+    writer->write(get_bootstrap_name(leakp)); // maps to synthetic name -> "bootstrap"
+  } else {
+    writer->write(artifact_id(cld)); // class loader instance id
+    writer->write(artifact_id(class_loader_klass)); // class loader type id
+    writer->write(mark_symbol(cld->name(), leakp)); // class loader instance name
+  }
+  return 1;
+}
+
+int write__classloader(JfrCheckpointWriter* writer, const void* c) {
+  assert(c != NULL, "invariant");
+  CldPtr cld = (CldPtr)c;
+  set_serialized(cld);
+  return write_classloader(writer, cld, false);
+}
+
+int write__classloader__leakp(JfrCheckpointWriter* writer, const void* c) {
+  assert(c != NULL, "invariant");
+  CldPtr cld = (CldPtr)c;
+  CLEAR_LEAKP(cld);
+  return write_classloader(writer, cld, true);
+}
+
+static void do_class_loader_data(ClassLoaderData* cld) {
+  do_previous_epoch_artifact(_subsystem_callback, cld);
+}
 
 class CldFieldSelector {
  public:
@@ -700,289 +533,328 @@
   }
 };
 
-typedef KlassToFieldEnvelope<CldFieldSelector, CldWriterWithClear> KlassCldWriterWithClear;
-typedef KlassToFieldEnvelope<CldFieldSelector, CompositeCldWriterWithClear> KlassCompositeCldWriterWithClear;
+class CLDCallback : public CLDClosure {
+ public:
+  CLDCallback() {}
+  void do_cld(ClassLoaderData* cld) {
+    assert(cld != NULL, "invariant");
+    if (cld->is_unsafe_anonymous()) {
+      return;
+    }
+    do_class_loader_data(cld);
+  }
+};
+
+static void do_class_loaders() {
+  CLDCallback cld_cb;
+  ClassLoaderDataGraph::loaded_cld_do(&cld_cb);
+}
+
+typedef SerializePredicate<CldPtr> CldPredicate;
+typedef JfrPredicatedTypeWriterImplHost<CldPtr, CldPredicate, write__classloader> CldWriterImpl;
+typedef JfrTypeWriterHost<CldWriterImpl, TYPE_CLASSLOADER> CldWriter;
+typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
+typedef JfrArtifactCallbackHost<CldPtr, CldWriterWithClear> CldCallback;
+typedef KlassToFieldEnvelope<CldFieldSelector, CldWriter> KlassCldWriter;
 
-/*
- * Composite operation
- *
- * LeakpClassLoaderWriter ->
- *   ClassLoaderWriter ->
- *     ClearArtifact<ClassLoaderData>
- */
-void JfrTypeSet::write_class_loader_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
-  assert(_artifacts->has_klass_entries(), "invariant");
-  ClearArtifact<CldPtr> clear(_class_unload);
-  CldWriter cldw(writer, _artifacts, _class_unload);
-  if (leakp_writer == NULL) {
+typedef LeakPredicate<CldPtr> LeakCldPredicate;
+typedef JfrPredicatedTypeWriterImplHost<CldPtr, LeakCldPredicate, write__classloader__leakp> LeakCldWriterImpl;
+typedef JfrTypeWriterHost<LeakCldWriterImpl, TYPE_CLASSLOADER> LeakCldWriter;
+
+typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
+typedef KlassToFieldEnvelope<CldFieldSelector, CompositeCldWriter> KlassCompositeCldWriter;
+typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
+typedef JfrArtifactCallbackHost<CldPtr, CompositeCldWriterWithClear> CompositeCldCallback;
+
+static void write_classloaders() {
+  assert(_writer != NULL, "invariant");
+  CldWriter cldw(_writer, _class_unload);
+  KlassCldWriter kcw(&cldw);
+  if (current_epoch()) {
+    _artifacts->iterate_klasses(kcw);
+    _artifacts->tally(cldw);
+    return;
+  }
+  assert(previous_epoch(), "invariant");
+  if (_leakp_writer == NULL) {
+    _artifacts->iterate_klasses(kcw);
+    ClearArtifact<CldPtr> clear;
     CldWriterWithClear cldwwc(&cldw, &clear);
-    KlassCldWriterWithClear kcldwwc(&cldwwc);
-    _artifacts->iterate_klasses(kcldwwc);
     CldCallback callback(&cldwwc);
     _subsystem_callback = &callback;
     do_class_loaders();
-    return;
+  } else {
+    LeakCldWriter lcldw(_leakp_writer, _class_unload);
+    CompositeCldWriter ccldw(&lcldw, &cldw);
+    KlassCompositeCldWriter kccldw(&ccldw);
+    _artifacts->iterate_klasses(kccldw);
+    ClearArtifact<CldPtr> clear;
+    CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
+    CompositeCldCallback callback(&ccldwwc);
+    _subsystem_callback = &callback;
+    do_class_loaders();
   }
-  LeakCldWriter lcldw(leakp_writer, _artifacts, _class_unload);
-  CompositeCldWriter ccldw(&lcldw, &cldw);
-  CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
-  KlassCompositeCldWriterWithClear kcclwwc(&ccldwwc);
-  _artifacts->iterate_klasses(kcclwwc);
-  CompositeCldCallback callback(&ccldwwc);
-  _subsystem_callback = &callback;
-  do_class_loaders();
+  _artifacts->tally(cldw);
+}
+
+static u1 get_visibility(MethodPtr method) {
+  assert(method != NULL, "invariant");
+  return const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0;
+}
+
+template <>
+void set_serialized<Method>(MethodPtr method) {
+  assert(method != NULL, "invariant");
+  SET_METHOD_SERIALIZED(method);
+  assert(IS_METHOD_SERIALIZED(method), "invariant");
 }
 
-template <bool predicate_bool, typename MethodFunctor>
+static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leakp) {
+  assert(writer != NULL, "invariant");
+  assert(method != NULL, "invariant");
+  assert(_artifacts != NULL, "invariant");
+  KlassPtr klass = method->method_holder();
+  assert(klass != NULL, "invariant");
+  writer->write(method_id(klass, method));
+  writer->write(artifact_id(klass));
+  writer->write(mark_symbol(method->name(), leakp));
+  writer->write(mark_symbol(method->signature(), leakp));
+  writer->write((u2)get_flags(method));
+  writer->write(get_visibility(method));
+  return 1;
+}
+
+int write__method(JfrCheckpointWriter* writer, const void* m) {
+  assert(m != NULL, "invariant");
+  MethodPtr method = (MethodPtr)m;
+  set_serialized(method);
+  return write_method(writer, method, false);
+}
+
+int write__method__leakp(JfrCheckpointWriter* writer, const void* m) {
+  assert(m != NULL, "invariant");
+  MethodPtr method = (MethodPtr)m;
+  return write_method(writer, method, true);
+}
+
+template <typename MethodCallback, typename KlassCallback, bool leakp>
 class MethodIteratorHost {
  private:
-  MethodFunctor _method_functor;
-  MethodUsedPredicate<predicate_bool> _method_used_predicate;
-  MethodFlagPredicate _method_flag_predicate;
-
+  MethodCallback _method_cb;
+  KlassCallback _klass_cb;
+  MethodUsedPredicate<leakp> _method_used_predicate;
+  MethodFlagPredicate<leakp> _method_flag_predicate;
  public:
   MethodIteratorHost(JfrCheckpointWriter* writer,
-                     JfrArtifactSet* artifacts,
-                     bool class_unload,
+                     bool current_epoch = false,
+                     bool class_unload = false,
                      bool skip_header = false) :
-    _method_functor(writer, artifacts, class_unload, skip_header),
-    _method_used_predicate(class_unload),
-    _method_flag_predicate(class_unload) {}
+    _method_cb(writer, class_unload, skip_header),
+    _klass_cb(writer, class_unload, skip_header),
+    _method_used_predicate(current_epoch),
+    _method_flag_predicate(current_epoch) {}
 
   bool operator()(KlassPtr klass) {
     if (_method_used_predicate(klass)) {
-      assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
-      const InstanceKlass* ik = InstanceKlass::cast(klass);
+      const InstanceKlass* const ik = InstanceKlass::cast(klass);
       const int len = ik->methods()->length();
       for (int i = 0; i < len; ++i) {
         MethodPtr method = ik->methods()->at(i);
         if (_method_flag_predicate(method)) {
-          _method_functor(method);
+          _method_cb(method);
         }
       }
     }
-    return true;
+    return _klass_cb(klass);
   }
 
-  int count() const { return _method_functor.count(); }
-  void add(int count) { _method_functor.add(count); }
+  int count() const { return _method_cb.count(); }
+  void add(int count) { _method_cb.add(count); }
 };
 
-typedef MethodIteratorHost<true /*leakp */,  MethodWriterImpl> LeakMethodWriter;
-typedef MethodIteratorHost<false, MethodWriterImpl> MethodWriter;
-typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
-
-/*
- * Composite operation
- *
- * LeakpMethodWriter ->
- *   MethodWriter
- */
-void JfrTypeSet::write_method_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
-  assert(_artifacts->has_klass_entries(), "invariant");
-  MethodWriter mw(writer, _artifacts, _class_unload);
-  if (leakp_writer == NULL) {
-    _artifacts->iterate_klasses(mw);
-    return;
-  }
-  LeakMethodWriter lpmw(leakp_writer, _artifacts, _class_unload);
-  CompositeMethodWriter cmw(&lpmw, &mw);
-  _artifacts->iterate_klasses(cmw);
-}
-static void write_symbols_leakp(JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
-  assert(leakp_writer != NULL, "invariant");
-  assert(artifacts != NULL, "invariant");
-  LeakKlassSymbolWriter lpksw(leakp_writer, artifacts, class_unload);
-  artifacts->iterate_klasses(lpksw);
-}
-static void write_symbols(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
-  assert(writer != NULL, "invariant");
-  assert(artifacts != NULL, "invariant");
-  if (leakp_writer != NULL) {
-    write_symbols_leakp(leakp_writer, artifacts, class_unload);
-  }
-  // iterate all registered symbols
-  SymbolEntryWriter symbol_writer(writer, artifacts, class_unload);
-  artifacts->iterate_symbols(symbol_writer);
-  CStringEntryWriter cstring_writer(writer, artifacts, class_unload, true); // skip header
-  artifacts->iterate_cstrings(cstring_writer);
-  symbol_writer.add(cstring_writer.count());
-}
-
-bool JfrTypeSet::_class_unload = false;
-JfrArtifactSet* JfrTypeSet::_artifacts = NULL;
-JfrArtifactClosure* JfrTypeSet::_subsystem_callback = NULL;
-
-void JfrTypeSet::write_symbol_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
-  assert(writer != NULL, "invariant");
-  assert(_artifacts->has_klass_entries(), "invariant");
-  write_symbols(writer, leakp_writer, _artifacts, _class_unload);
-}
-
-void JfrTypeSet::do_unloaded_klass(Klass* klass) {
-  assert(klass != NULL, "invariant");
-  assert(_subsystem_callback != NULL, "invariant");
-  if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) {
-    JfrEventClasses::increment_unloaded_event_class();
-  }
-  if (USED_THIS_EPOCH(klass)) { // includes leakp subset
-    _subsystem_callback->do_artifact(klass);
-    return;
-  }
-  if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
-    SET_LEAKP_USED_THIS_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
-    _subsystem_callback->do_artifact(klass);
-  }
-}
-
-void JfrTypeSet::do_klass(Klass* klass) {
-  assert(klass != NULL, "invariant");
-  assert(_subsystem_callback != NULL, "invariant");
-  if (USED_PREV_EPOCH(klass)) { // includes leakp subset
-    _subsystem_callback->do_artifact(klass);
-    return;
-  }
-  if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
-    SET_LEAKP_USED_PREV_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
-    _subsystem_callback->do_artifact(klass);
-  }
-}
-
-void JfrTypeSet::do_klasses() {
-  if (_class_unload) {
-    ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass);
-    return;
-  }
-  ClassLoaderDataGraph::classes_do(&do_klass);
-}
-
-void JfrTypeSet::do_unloaded_package(PackageEntry* entry) {
-  assert(entry != NULL, "invariant");
-  assert(_subsystem_callback != NULL, "invariant");
-  if (ANY_USED_THIS_EPOCH(entry)) { // includes leakp subset
-    _subsystem_callback->do_artifact(entry);
-  }
-}
-
-void JfrTypeSet::do_package(PackageEntry* entry) {
-  assert(_subsystem_callback != NULL, "invariant");
-  if (ANY_USED_PREV_EPOCH(entry)) { // includes leakp subset
-    _subsystem_callback->do_artifact(entry);
-  }
-}
-
-void JfrTypeSet::do_packages() {
-  if (_class_unload) {
-    ClassLoaderDataGraph::packages_unloading_do(&do_unloaded_package);
-    return;
-  }
-  ClassLoaderDataGraph::packages_do(&do_package);
-}
-void JfrTypeSet::do_unloaded_module(ModuleEntry* entry) {
-  assert(entry != NULL, "invariant");
-  assert(_subsystem_callback != NULL, "invariant");
-  if (ANY_USED_THIS_EPOCH(entry)) { // includes leakp subset
-    _subsystem_callback->do_artifact(entry);
-  }
-}
-
-void JfrTypeSet::do_module(ModuleEntry* entry) {
-  assert(_subsystem_callback != NULL, "invariant");
-  if (ANY_USED_PREV_EPOCH(entry)) { // includes leakp subset
-    _subsystem_callback->do_artifact(entry);
-  }
-}
-
-void JfrTypeSet::do_modules() {
-  if (_class_unload) {
-    ClassLoaderDataGraph::modules_unloading_do(&do_unloaded_module);
-    return;
-  }
-  ClassLoaderDataGraph::modules_do(&do_module);
-}
-
-void JfrTypeSet::do_unloaded_class_loader_data(ClassLoaderData* cld) {
-  assert(_subsystem_callback != NULL, "invariant");
-  if (ANY_USED_THIS_EPOCH(cld)) { // includes leakp subset
-    _subsystem_callback->do_artifact(cld);
-  }
-}
-
-void JfrTypeSet::do_class_loader_data(ClassLoaderData* cld) {
-  assert(_subsystem_callback != NULL, "invariant");
-  if (ANY_USED_PREV_EPOCH(cld)) { // includes leakp subset
-    _subsystem_callback->do_artifact(cld);
-  }
-}
-
-class CLDCallback : public CLDClosure {
- private:
-  bool _class_unload;
+template <typename T, template <typename> class Impl>
+class Wrapper {
+  Impl<T> _t;
  public:
-  CLDCallback(bool class_unload) : _class_unload(class_unload) {}
-  void do_cld(ClassLoaderData* cld) {
-     assert(cld != NULL, "invariant");
-    if (cld->is_unsafe_anonymous()) {
-      return;
-    }
-    if (_class_unload) {
-      JfrTypeSet::do_unloaded_class_loader_data(cld);
-      return;
-    }
-    JfrTypeSet::do_class_loader_data(cld);
+  Wrapper(JfrCheckpointWriter*, bool, bool) : _t() {}
+  bool operator()(T const& value) {
+    return _t(value);
   }
 };
 
-void JfrTypeSet::do_class_loaders() {
-  CLDCallback cld_cb(_class_unload);
-  if (_class_unload) {
-    ClassLoaderDataGraph::cld_unloading_do(&cld_cb);
-    return;
+typedef SerializePredicate<MethodPtr> MethodPredicate;
+typedef JfrPredicatedTypeWriterImplHost<MethodPtr, MethodPredicate, write__method> MethodWriterImplTarget;
+typedef Wrapper<KlassPtr, Stub> KlassCallbackStub;
+typedef JfrTypeWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
+typedef MethodIteratorHost<MethodWriterImpl, KlassCallbackStub, false> MethodWriter;
+
+typedef LeakPredicate<MethodPtr> LeakMethodPredicate;
+typedef JfrPredicatedTypeWriterImplHost<MethodPtr, LeakMethodPredicate, write__method__leakp> LeakMethodWriterImplTarget;
+typedef JfrTypeWriterHost<LeakMethodWriterImplTarget, TYPE_METHOD> LeakMethodWriterImpl;
+typedef MethodIteratorHost<LeakMethodWriterImpl, KlassCallbackStub, true> LeakMethodWriter;
+typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
+
+static void write_methods() {
+  assert(_writer != NULL, "invariant");
+  MethodWriter mw(_writer, current_epoch(), _class_unload);
+  if (_leakp_writer == NULL) {
+    _artifacts->iterate_klasses(mw);
+  } else {
+    LeakMethodWriter lpmw(_leakp_writer, current_epoch(), _class_unload);
+    CompositeMethodWriter cmw(&lpmw, &mw);
+    _artifacts->iterate_klasses(cmw);
   }
-  ClassLoaderDataGraph::loaded_cld_do(&cld_cb);
+  _artifacts->tally(mw);
+}
+
+template <>
+void set_serialized<JfrSymbolId::SymbolEntry>(SymbolEntryPtr ptr) {
+  assert(ptr != NULL, "invariant");
+  ptr->set_serialized();
+  assert(ptr->is_serialized(), "invariant");
+}
+
+template <>
+void set_serialized<JfrSymbolId::CStringEntry>(CStringEntryPtr ptr) {
+  assert(ptr != NULL, "invariant");
+  ptr->set_serialized();
+  assert(ptr->is_serialized(), "invariant");
+}
+
+static int write_symbol(JfrCheckpointWriter* writer, SymbolEntryPtr entry, bool leakp) {
+  assert(writer != NULL, "invariant");
+  assert(entry != NULL, "invariant");
+  ResourceMark rm;
+  writer->write(create_symbol_id(entry->id()));
+  writer->write(entry->value()->as_C_string());
+  return 1;
+}
+
+int write__symbol(JfrCheckpointWriter* writer, const void* e) {
+  assert(e != NULL, "invariant");
+  SymbolEntryPtr entry = (SymbolEntryPtr)e;
+  set_serialized(entry);
+  return write_symbol(writer, entry, false);
+}
+
+int write__symbol__leakp(JfrCheckpointWriter* writer, const void* e) {
+  assert(e != NULL, "invariant");
+  SymbolEntryPtr entry = (SymbolEntryPtr)e;
+  return write_symbol(writer, entry, true);
+}
+
+static int write_cstring(JfrCheckpointWriter* writer, CStringEntryPtr entry, bool leakp) {
+  assert(writer != NULL, "invariant");
+  assert(entry != NULL, "invariant");
+  writer->write(create_symbol_id(entry->id()));
+  writer->write(entry->value());
+  return 1;
+}
+
+int write__cstring(JfrCheckpointWriter* writer, const void* e) {
+  assert(e != NULL, "invariant");
+  CStringEntryPtr entry = (CStringEntryPtr)e;
+  set_serialized(entry);
+  return write_cstring(writer, entry, false);
 }
 
-static void clear_artifacts(JfrArtifactSet* artifacts,
-                            bool class_unload) {
-  assert(artifacts != NULL, "invariant");
-  assert(artifacts->has_klass_entries(), "invariant");
+int write__cstring__leakp(JfrCheckpointWriter* writer, const void* e) {
+  assert(e != NULL, "invariant");
+  CStringEntryPtr entry = (CStringEntryPtr)e;
+  return write_cstring(writer, entry, true);
+}
+
+typedef SymbolPredicate<SymbolEntryPtr, false> SymPredicate;
+typedef JfrPredicatedTypeWriterImplHost<SymbolEntryPtr, SymPredicate, write__symbol> SymbolEntryWriterImpl;
+typedef JfrTypeWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
+typedef SymbolPredicate<CStringEntryPtr, false> CStringPredicate;
+typedef JfrPredicatedTypeWriterImplHost<CStringEntryPtr, CStringPredicate, write__cstring> CStringEntryWriterImpl;
+typedef JfrTypeWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
+
+typedef SymbolPredicate<SymbolEntryPtr, true> LeakSymPredicate;
+typedef JfrPredicatedTypeWriterImplHost<SymbolEntryPtr, LeakSymPredicate, write__symbol__leakp> LeakSymbolEntryWriterImpl;
+typedef JfrTypeWriterHost<LeakSymbolEntryWriterImpl, TYPE_SYMBOL> LeakSymbolEntryWriter;
+typedef CompositeFunctor<SymbolEntryPtr, LeakSymbolEntryWriter, SymbolEntryWriter> CompositeSymbolWriter;
+typedef SymbolPredicate<CStringEntryPtr, true> LeakCStringPredicate;
+typedef JfrPredicatedTypeWriterImplHost<CStringEntryPtr, LeakCStringPredicate, write__cstring__leakp> LeakCStringEntryWriterImpl;
+typedef JfrTypeWriterHost<LeakCStringEntryWriterImpl, TYPE_SYMBOL> LeakCStringEntryWriter;
+typedef CompositeFunctor<CStringEntryPtr, LeakCStringEntryWriter, CStringEntryWriter> CompositeCStringWriter;
+
+static void write_symbols_with_leakp() {
+  assert(_leakp_writer != NULL, "invariant");
+  SymbolEntryWriter sw(_writer, _class_unload);
+  LeakSymbolEntryWriter lsw(_leakp_writer, _class_unload);
+  CompositeSymbolWriter csw(&lsw, &sw);
+  _artifacts->iterate_symbols(csw);
+  CStringEntryWriter ccsw(_writer, _class_unload, true); // skip header
+  LeakCStringEntryWriter lccsw(_leakp_writer, _class_unload, true); // skip header
+  CompositeCStringWriter cccsw(&lccsw, &ccsw);
+  _artifacts->iterate_cstrings(cccsw);
+  sw.add(ccsw.count());
+  lsw.add(lccsw.count());
+  _artifacts->tally(sw);
+}
 
-  // untag
-  ClearKlassAndMethods clear(class_unload);
-  artifacts->iterate_klasses(clear);
-  artifacts->clear();
+static void write_symbols() {
+  assert(_writer != NULL, "invariant");
+  if (_leakp_writer != NULL) {
+    write_symbols_with_leakp();
+    return;
+  }
+  SymbolEntryWriter sw(_writer, _class_unload);
+  _artifacts->iterate_symbols(sw);
+  CStringEntryWriter csw(_writer, _class_unload, true); // skip header
+  _artifacts->iterate_cstrings(csw);
+  sw.add(csw.count());
+  _artifacts->tally(sw);
+}
+
+typedef Wrapper<KlassPtr, ClearArtifact> ClearKlassBits;
+typedef Wrapper<MethodPtr, ClearArtifact> ClearMethodFlag;
+typedef MethodIteratorHost<ClearMethodFlag, ClearKlassBits, false> ClearKlassAndMethods;
+
+static size_t teardown() {
+  assert(_artifacts != NULL, "invariant");
+  const size_t total_count = _artifacts->total_count();
+  if (previous_epoch()) {
+    assert(_writer != NULL, "invariant");
+    ClearKlassAndMethods clear(_writer);
+    _artifacts->iterate_klasses(clear);
+    _artifacts->clear();
+    ++checkpoint_id;
+  }
+  return total_count;
+}
+
+static void setup(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload) {
+  _writer = writer;
+  _leakp_writer = leakp_writer;
+  _class_unload = class_unload;
+  if (_artifacts == NULL) {
+    _artifacts = new JfrArtifactSet(class_unload);
+  } else {
+    _artifacts->initialize(class_unload);
+  }
+  assert(_artifacts != NULL, "invariant");
+  assert(!_artifacts->has_klass_entries(), "invariant");
 }
 
 /**
  * Write all "tagged" (in-use) constant artifacts and their dependencies.
  */
-void JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload) {
+size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload) {
   assert(writer != NULL, "invariant");
   ResourceMark rm;
-  // initialization begin
-  _class_unload = class_unload;
-  ++checkpoint_id;
-  if (_artifacts == NULL) {
-    _artifacts = new JfrArtifactSet(class_unload);
-    _subsystem_callback = NULL;
-  } else {
-    _artifacts->initialize(class_unload);
-    _subsystem_callback = NULL;
-  }
-  assert(_artifacts != NULL, "invariant");
-  assert(!_artifacts->has_klass_entries(), "invariant");
-  assert(_subsystem_callback == NULL, "invariant");
-  // initialization complete
-
+  setup(writer, leakp_writer, class_unload);
   // write order is important because an individual write step
   // might tag an artifact to be written in a subsequent step
-  write_klass_constants(writer, leakp_writer);
-  if (_artifacts->has_klass_entries()) {
-    write_package_constants(writer, leakp_writer);
-    write_module_constants(writer, leakp_writer);
-    write_class_loader_constants(writer, leakp_writer);
-    write_method_constants(writer, leakp_writer);
-    write_symbol_constants(writer, leakp_writer);
-    clear_artifacts(_artifacts, class_unload);
+  if (!write_klasses()) {
+    return 0;
   }
+  write_packages();
+  write_modules();
+  write_classloaders();
+  write_methods();
+  write_symbols();
+  return teardown();
 }