src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
changeset 50113 caf115bb98ad
child 50634 c349d409262a
equal deleted inserted replaced
50112:7a2a740815b7 50113:caf115bb98ad
       
     1 /*
       
     2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "classfile/classLoaderData.inline.hpp"
       
    27 #include "classfile/javaClasses.inline.hpp"
       
    28 #include "classfile/moduleEntry.hpp"
       
    29 #include "classfile/packageEntry.hpp"
       
    30 #include "classfile/symbolTable.hpp"
       
    31 #include "classfile/systemDictionary.hpp"
       
    32 #include "jfr/jfr.hpp"
       
    33 #include "jfr/jni/jfrGetAllEventClasses.hpp"
       
    34 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
       
    35 #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
       
    36 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
       
    37 #include "jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp"
       
    38 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
       
    39 #include "jfr/recorder/storage/jfrBuffer.hpp"
       
    40 #include "jfr/utilities/jfrHashtable.hpp"
       
    41 #include "jfr/utilities/jfrTypes.hpp"
       
    42 #include "memory/iterator.hpp"
       
    43 #include "memory/resourceArea.hpp"
       
    44 #include "oops/instanceKlass.hpp"
       
    45 #include "oops/objArrayKlass.hpp"
       
    46 #include "oops/oop.inline.hpp"
       
    47 #include "memory/resourceArea.hpp"
       
    48 #include "utilities/accessFlags.hpp"
       
    49 
       
    50 // incremented on each checkpoint
       
    51 static u8 checkpoint_id = 0;
       
    52 
       
    53 // creates a unique id by combining a checkpoint relative symbol id (2^24)
       
    54 // with the current checkpoint id (2^40)
       
    55 #define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))
       
    56 
       
    57 typedef const Klass* KlassPtr;
       
    58 typedef const PackageEntry* PkgPtr;
       
    59 typedef const ModuleEntry* ModPtr;
       
    60 typedef const ClassLoaderData* CldPtr;
       
    61 typedef const Method* MethodPtr;
       
    62 typedef const Symbol* SymbolPtr;
       
    63 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
       
    64 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
       
    65 
       
    66 static traceid module_id(PkgPtr pkg) {
       
    67   assert(pkg != NULL, "invariant");
       
    68   ModPtr module_entry = pkg->module();
       
    69   return module_entry != NULL && module_entry->is_named() ? TRACE_ID(module_entry) : 0;
       
    70 }
       
    71 
       
    72 static traceid package_id(KlassPtr klass) {
       
    73   assert(klass != NULL, "invariant");
       
    74   PkgPtr pkg_entry = klass->package();
       
    75   return pkg_entry == NULL ? 0 : TRACE_ID(pkg_entry);
       
    76 }
       
    77 
       
    78 static traceid cld_id(CldPtr cld) {
       
    79   assert(cld != NULL, "invariant");
       
    80   return cld->is_anonymous() ? 0 : TRACE_ID(cld);
       
    81 }
       
    82 
       
    83 static void tag_leakp_klass_artifacts(KlassPtr k, bool class_unload) {
       
    84   assert(k != NULL, "invariant");
       
    85   PkgPtr pkg = k->package();
       
    86   if (pkg != NULL) {
       
    87     tag_leakp_artifact(pkg, class_unload);
       
    88     ModPtr module = pkg->module();
       
    89     if (module != NULL) {
       
    90       tag_leakp_artifact(module, class_unload);
       
    91     }
       
    92   }
       
    93   CldPtr cld = k->class_loader_data();
       
    94   assert(cld != NULL, "invariant");
       
    95   if (!cld->is_anonymous()) {
       
    96     tag_leakp_artifact(cld, class_unload);
       
    97   }
       
    98 }
       
    99 
       
   100 class TagLeakpKlassArtifact {
       
   101   bool _class_unload;
       
   102  public:
       
   103   TagLeakpKlassArtifact(bool class_unload) : _class_unload(class_unload) {}
       
   104   bool operator()(KlassPtr klass) {
       
   105     if (_class_unload) {
       
   106       if (LEAKP_USED_THIS_EPOCH(klass)) {
       
   107         tag_leakp_klass_artifacts(klass, _class_unload);
       
   108       }
       
   109     } else {
       
   110       if (LEAKP_USED_PREV_EPOCH(klass)) {
       
   111         tag_leakp_klass_artifacts(klass, _class_unload);
       
   112       }
       
   113     }
       
   114     return true;
       
   115   }
       
   116 };
       
   117 
       
   118 /*
       
   119  * In C++03, functions used as template parameters must have external linkage;
       
   120  * this restriction was removed in C++11. Change back to "static" and
       
   121  * rename functions when C++11 becomes available.
       
   122  *
       
   123  * The weird naming is an effort to decrease the risk of name clashes.
       
   124  */
       
   125 
       
   126 int write__artifact__klass(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
       
   127   assert(writer != NULL, "invariant");
       
   128   assert(artifacts != NULL, "invariant");
       
   129   assert(k != NULL, "invariant");
       
   130   KlassPtr klass = (KlassPtr)k;
       
   131   traceid pkg_id = 0;
       
   132   KlassPtr theklass = klass;
       
   133   if (theklass->is_objArray_klass()) {
       
   134     const ObjArrayKlass* obj_arr_klass = ObjArrayKlass::cast(klass);
       
   135     theklass = obj_arr_klass->bottom_klass();
       
   136   }
       
   137   if (theklass->is_instance_klass()) {
       
   138     pkg_id = package_id(theklass);
       
   139   } else {
       
   140     assert(theklass->is_typeArray_klass(), "invariant");
       
   141   }
       
   142   const traceid symbol_id = artifacts->mark(klass);
       
   143   assert(symbol_id > 0, "need to have an address for symbol!");
       
   144   writer->write(TRACE_ID(klass));
       
   145   writer->write(cld_id(klass->class_loader_data()));
       
   146   writer->write((traceid)CREATE_SYMBOL_ID(symbol_id));
       
   147   writer->write(pkg_id);
       
   148   writer->write((s4)klass->access_flags().get_flags());
       
   149   return 1;
       
   150 }
       
   151 
       
   152 typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
       
   153 typedef JfrPredicatedArtifactWriterImplHost<KlassPtr, LeakKlassPredicate, write__artifact__klass> LeakKlassWriterImpl;
       
   154 typedef JfrArtifactWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
       
   155 typedef JfrArtifactWriterImplHost<KlassPtr, write__artifact__klass> KlassWriterImpl;
       
   156 typedef JfrArtifactWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
       
   157 
       
   158 int write__artifact__method(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
       
   159   assert(writer != NULL, "invariant");
       
   160   assert(artifacts != NULL, "invariant");
       
   161   assert(m != NULL, "invariant");
       
   162   MethodPtr method = (MethodPtr)m;
       
   163   const traceid method_name_symbol_id = artifacts->mark(method->name());
       
   164   assert(method_name_symbol_id > 0, "invariant");
       
   165   const traceid method_sig_symbol_id = artifacts->mark(method->signature());
       
   166   assert(method_sig_symbol_id > 0, "invariant");
       
   167   KlassPtr klass = method->method_holder();
       
   168   assert(klass != NULL, "invariant");
       
   169   assert(METHOD_USED_ANY_EPOCH(klass), "invariant");
       
   170   writer->write((u8)METHOD_ID(klass, method));
       
   171   writer->write((u8)TRACE_ID(klass));
       
   172   writer->write((u8)CREATE_SYMBOL_ID(method_name_symbol_id));
       
   173   writer->write((u8)CREATE_SYMBOL_ID(method_sig_symbol_id));
       
   174   writer->write((u2)method->access_flags().get_flags());
       
   175   writer->write(const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0);
       
   176   return 1;
       
   177 }
       
   178 
       
   179 typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget;
       
   180 typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
       
   181 
       
   182 int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) {
       
   183   assert(writer != NULL, "invariant");
       
   184   assert(artifacts != NULL, "invariant");
       
   185   assert(p != NULL, "invariant");
       
   186   PkgPtr pkg = (PkgPtr)p;
       
   187   Symbol* const pkg_name = pkg->name();
       
   188   const traceid package_name_symbol_id = pkg_name != NULL ? artifacts->mark(pkg_name) : 0;
       
   189   assert(package_name_symbol_id > 0, "invariant");
       
   190   writer->write((traceid)TRACE_ID(pkg));
       
   191   writer->write((traceid)CREATE_SYMBOL_ID(package_name_symbol_id));
       
   192   writer->write(module_id(pkg));
       
   193   writer->write((bool)pkg->is_exported());
       
   194   return 1;
       
   195 }
       
   196 
       
   197 typedef LeakPredicate<PkgPtr> LeakPackagePredicate;
       
   198 int _compare_pkg_ptr_(PkgPtr const& lhs, PkgPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
       
   199 typedef UniquePredicate<PkgPtr, _compare_pkg_ptr_> PackagePredicate;
       
   200 typedef JfrPredicatedArtifactWriterImplHost<PkgPtr, LeakPackagePredicate, write__artifact__package> LeakPackageWriterImpl;
       
   201 typedef JfrPredicatedArtifactWriterImplHost<PkgPtr, PackagePredicate, write__artifact__package> PackageWriterImpl;
       
   202 typedef JfrArtifactWriterHost<LeakPackageWriterImpl, TYPE_PACKAGE> LeakPackageWriter;
       
   203 typedef JfrArtifactWriterHost<PackageWriterImpl, TYPE_PACKAGE> PackageWriter;
       
   204 
       
   205 int write__artifact__module(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
       
   206   assert( m != NULL, "invariant");
       
   207   ModPtr entry = (ModPtr)m;
       
   208   Symbol* const module_name = entry->name();
       
   209   const traceid module_name_symbol_id = module_name != NULL ? artifacts->mark(module_name) : 0;
       
   210   Symbol* const module_version = entry->version();
       
   211   const traceid module_version_symbol_id = module_version != NULL ? artifacts->mark(module_version) : 0;
       
   212   Symbol* const module_location = entry->location();
       
   213   const traceid module_location_symbol_id = module_location != NULL ? artifacts->mark(module_location) : 0;
       
   214   writer->write((traceid)TRACE_ID(entry));
       
   215   writer->write(module_name_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_name_symbol_id));
       
   216   writer->write(module_version_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_version_symbol_id));
       
   217   writer->write(module_location_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_location_symbol_id));
       
   218   writer->write(cld_id(entry->loader_data()));
       
   219   return 1;
       
   220 }
       
   221 
       
   222 typedef LeakPredicate<ModPtr> LeakModulePredicate;
       
   223 int _compare_mod_ptr_(ModPtr const& lhs, ModPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
       
   224 typedef UniquePredicate<ModPtr, _compare_mod_ptr_> ModulePredicate;
       
   225 typedef JfrPredicatedArtifactWriterImplHost<ModPtr, LeakModulePredicate, write__artifact__module> LeakModuleWriterImpl;
       
   226 typedef JfrPredicatedArtifactWriterImplHost<ModPtr, ModulePredicate, write__artifact__module> ModuleWriterImpl;
       
   227 typedef JfrArtifactWriterHost<LeakModuleWriterImpl, TYPE_MODULE> LeakModuleWriter;
       
   228 typedef JfrArtifactWriterHost<ModuleWriterImpl, TYPE_MODULE> ModuleWriter;
       
   229 
       
   230 int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) {
       
   231   assert(c != NULL, "invariant");
       
   232   CldPtr cld = (CldPtr)c;
       
   233   assert(!cld->is_anonymous(), "invariant");
       
   234   const traceid cld_id = TRACE_ID(cld);
       
   235   // class loader type
       
   236   const Klass* class_loader_klass = cld->class_loader_klass();
       
   237   if (class_loader_klass == NULL) {
       
   238     // (primordial) boot class loader
       
   239     writer->write(cld_id); // class loader instance id
       
   240     writer->write((traceid)0);  // class loader type id (absence of)
       
   241     writer->write((traceid)CREATE_SYMBOL_ID(1)); // 1 maps to synthetic name -> "boot"
       
   242   } else {
       
   243     Symbol* symbol_name = cld->class_loader_name();
       
   244     const traceid symbol_name_id = symbol_name != NULL ? artifacts->mark(symbol_name) : 0;
       
   245     writer->write(cld_id); // class loader instance id
       
   246     writer->write(TRACE_ID(class_loader_klass)); // class loader type id
       
   247     writer->write(symbol_name_id == 0 ? (traceid)0 :
       
   248       (traceid)CREATE_SYMBOL_ID(symbol_name_id)); // class loader instance name
       
   249   }
       
   250   return 1;
       
   251 }
       
   252 
       
   253 typedef LeakPredicate<CldPtr> LeakCldPredicate;
       
   254 int _compare_cld_ptr_(CldPtr const& lhs, CldPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
       
   255 typedef UniquePredicate<CldPtr, _compare_cld_ptr_> CldPredicate;
       
   256 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, LeakCldPredicate, write__artifact__classloader> LeakCldWriterImpl;
       
   257 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, CldPredicate, write__artifact__classloader> CldWriterImpl;
       
   258 typedef JfrArtifactWriterHost<LeakCldWriterImpl, TYPE_CLASSLOADER> LeakCldWriter;
       
   259 typedef JfrArtifactWriterHost<CldWriterImpl, TYPE_CLASSLOADER> CldWriter;
       
   260 
       
   261 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
       
   262 
       
   263 static int write__artifact__symbol__entry__(JfrCheckpointWriter* writer,
       
   264                                             SymbolEntryPtr entry) {
       
   265   assert(writer != NULL, "invariant");
       
   266   assert(entry != NULL, "invariant");
       
   267   ResourceMark rm;
       
   268   writer->write(CREATE_SYMBOL_ID(entry->id()));
       
   269   writer->write(entry->value()->as_C_string());
       
   270   return 1;
       
   271 }
       
   272 
       
   273 int write__artifact__symbol__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
       
   274   assert(e != NULL, "invariant");
       
   275   return write__artifact__symbol__entry__(writer, (SymbolEntryPtr)e);
       
   276 }
       
   277 
       
   278 typedef JfrArtifactWriterImplHost<SymbolEntryPtr, write__artifact__symbol__entry> SymbolEntryWriterImpl;
       
   279 typedef JfrArtifactWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
       
   280 
       
   281 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
       
   282 
       
   283 static int write__artifact__cstring__entry__(JfrCheckpointWriter* writer, CStringEntryPtr entry) {
       
   284   assert(writer != NULL, "invariant");
       
   285   assert(entry != NULL, "invariant");
       
   286   writer->write(CREATE_SYMBOL_ID(entry->id()));
       
   287   writer->write(entry->value());
       
   288   return 1;
       
   289 }
       
   290 
       
   291 int write__artifact__cstring__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
       
   292   assert(e != NULL, "invariant");
       
   293   return write__artifact__cstring__entry__(writer, (CStringEntryPtr)e);
       
   294 }
       
   295 
       
   296 typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__cstring__entry> CStringEntryWriterImpl;
       
   297 typedef JfrArtifactWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
       
   298 
       
   299 int write__artifact__klass__symbol(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
       
   300   assert(writer != NULL, "invariant");
       
   301   assert(artifacts != NULL, "invaiant");
       
   302   assert(k != NULL, "invariant");
       
   303   const InstanceKlass* const ik = (const InstanceKlass*)k;
       
   304   if (ik->is_anonymous()) {
       
   305     CStringEntryPtr entry =
       
   306       artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
       
   307     assert(entry != NULL, "invariant");
       
   308     return write__artifact__cstring__entry__(writer, entry);
       
   309   }
       
   310 
       
   311   SymbolEntryPtr entry = artifacts->map_symbol(JfrSymbolId::regular_klass_name_hash_code(ik));
       
   312   return write__artifact__symbol__entry__(writer, entry);
       
   313 }
       
   314 
       
   315 int _compare_traceid_(const traceid& lhs, const traceid& rhs) {
       
   316   return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
       
   317 }
       
   318 
       
   319 template <template <typename> class Predicate>
       
   320 class KlassSymbolWriterImpl {
       
   321  private:
       
   322   JfrCheckpointWriter* _writer;
       
   323   JfrArtifactSet* _artifacts;
       
   324   Predicate<KlassPtr> _predicate;
       
   325   MethodUsedPredicate<true> _method_used_predicate;
       
   326   MethodFlagPredicate _method_flag_predicate;
       
   327   UniquePredicate<traceid, _compare_traceid_> _unique_predicate;
       
   328 
       
   329   int klass_symbols(KlassPtr klass);
       
   330   int package_symbols(PkgPtr pkg);
       
   331   int module_symbols(ModPtr module);
       
   332   int class_loader_symbols(CldPtr cld);
       
   333   int method_symbols(KlassPtr klass);
       
   334 
       
   335  public:
       
   336   typedef KlassPtr Type;
       
   337   KlassSymbolWriterImpl(JfrCheckpointWriter* writer,
       
   338                         JfrArtifactSet* artifacts,
       
   339                         bool class_unload) : _writer(writer),
       
   340                                              _artifacts(artifacts),
       
   341                                              _predicate(class_unload),
       
   342                                              _method_used_predicate(class_unload),
       
   343                                              _method_flag_predicate(class_unload),
       
   344                                              _unique_predicate(class_unload) {}
       
   345 
       
   346   int operator()(KlassPtr klass) {
       
   347     assert(klass != NULL, "invariant");
       
   348     int count = 0;
       
   349     if (_predicate(klass)) {
       
   350       count += klass_symbols(klass);
       
   351       PkgPtr pkg = klass->package();
       
   352       if (pkg != NULL) {
       
   353         count += package_symbols(pkg);
       
   354         ModPtr module = pkg->module();
       
   355         if (module != NULL && module->is_named()) {
       
   356           count += module_symbols(module);
       
   357         }
       
   358       }
       
   359       CldPtr cld = klass->class_loader_data();
       
   360       assert(cld != NULL, "invariant");
       
   361       if (!cld->is_anonymous()) {
       
   362         count += class_loader_symbols(cld);
       
   363       }
       
   364       if (_method_used_predicate(klass)) {
       
   365         count += method_symbols(klass);
       
   366       }
       
   367     }
       
   368     return count;
       
   369   }
       
   370 };
       
   371 
       
   372 template <template <typename> class Predicate>
       
   373 int KlassSymbolWriterImpl<Predicate>::klass_symbols(KlassPtr klass) {
       
   374   assert(klass != NULL, "invariant");
       
   375   assert(_predicate(klass), "invariant");
       
   376   const InstanceKlass* const ik = (const InstanceKlass*)klass;
       
   377   if (ik->is_anonymous()) {
       
   378     CStringEntryPtr entry =
       
   379       this->_artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
       
   380     assert(entry != NULL, "invariant");
       
   381     return _unique_predicate(entry->id()) ? write__artifact__cstring__entry__(this->_writer, entry) : 0;
       
   382   }
       
   383   SymbolEntryPtr entry = this->_artifacts->map_symbol(ik->name());
       
   384   assert(entry != NULL, "invariant");
       
   385   return _unique_predicate(entry->id()) ? write__artifact__symbol__entry__(this->_writer, entry) : 0;
       
   386 }
       
   387 
       
   388 template <template <typename> class Predicate>
       
   389 int KlassSymbolWriterImpl<Predicate>::package_symbols(PkgPtr pkg) {
       
   390   assert(pkg != NULL, "invariant");
       
   391   SymbolPtr pkg_name = pkg->name();
       
   392   assert(pkg_name != NULL, "invariant");
       
   393   SymbolEntryPtr package_symbol = this->_artifacts->map_symbol(pkg_name);
       
   394   assert(package_symbol != NULL, "invariant");
       
   395   return _unique_predicate(package_symbol->id()) ?
       
   396     write__artifact__symbol__entry__(this->_writer, package_symbol) : 0;
       
   397 }
       
   398 
       
   399 template <template <typename> class Predicate>
       
   400 int KlassSymbolWriterImpl<Predicate>::module_symbols(ModPtr module) {
       
   401   assert(module != NULL, "invariant");
       
   402   assert(module->is_named(), "invariant");
       
   403   int count = 0;
       
   404   SymbolPtr sym = module->name();
       
   405   SymbolEntryPtr entry = NULL;
       
   406   if (sym != NULL) {
       
   407     entry = this->_artifacts->map_symbol(sym);
       
   408     assert(entry != NULL, "invariant");
       
   409     if (_unique_predicate(entry->id())) {
       
   410       count += write__artifact__symbol__entry__(this->_writer, entry);
       
   411     }
       
   412   }
       
   413   sym = module->version();
       
   414   if (sym != NULL) {
       
   415     entry = this->_artifacts->map_symbol(sym);
       
   416     assert(entry != NULL, "invariant");
       
   417     if (_unique_predicate(entry->id())) {
       
   418       count += write__artifact__symbol__entry__(this->_writer, entry);
       
   419     }
       
   420   }
       
   421   sym = module->location();
       
   422   if (sym != NULL) {
       
   423     entry = this->_artifacts->map_symbol(sym);
       
   424     assert(entry != NULL, "invariant");
       
   425     if (_unique_predicate(entry->id())) {
       
   426       count += write__artifact__symbol__entry__(this->_writer, entry);
       
   427     }
       
   428   }
       
   429   return count;
       
   430 }
       
   431 
       
   432 template <template <typename> class Predicate>
       
   433 int KlassSymbolWriterImpl<Predicate>::class_loader_symbols(CldPtr cld) {
       
   434   assert(cld != NULL, "invariant");
       
   435   assert(!cld->is_anonymous(), "invariant");
       
   436   int count = 0;
       
   437   // class loader type
       
   438   const Klass* class_loader_klass = cld->class_loader_klass();
       
   439   if (class_loader_klass == NULL) {
       
   440     // (primordial) boot class loader
       
   441     CStringEntryPtr entry = this->_artifacts->map_cstring(0);
       
   442     assert(entry != NULL, "invariant");
       
   443     assert(strncmp(entry->literal(),
       
   444       boot_class_loader_name,
       
   445       strlen(boot_class_loader_name)) == 0, "invariant");
       
   446     if (_unique_predicate(entry->id())) {
       
   447       count += write__artifact__cstring__entry__(this->_writer, entry);
       
   448     }
       
   449   } else {
       
   450     const Symbol* class_loader_name = cld->class_loader_name();
       
   451     if (class_loader_name != NULL) {
       
   452       SymbolEntryPtr entry = this->_artifacts->map_symbol(class_loader_name);
       
   453       assert(entry != NULL, "invariant");
       
   454       if (_unique_predicate(entry->id())) {
       
   455         count += write__artifact__symbol__entry__(this->_writer, entry);
       
   456       }
       
   457     }
       
   458   }
       
   459   return count;
       
   460 }
       
   461 
       
   462 template <template <typename> class Predicate>
       
   463 int KlassSymbolWriterImpl<Predicate>::method_symbols(KlassPtr klass) {
       
   464   assert(_predicate(klass), "invariant");
       
   465   assert(_method_used_predicate(klass), "invariant");
       
   466   assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
       
   467   int count = 0;
       
   468   const InstanceKlass* const ik = InstanceKlass::cast(klass);
       
   469   const int len = ik->methods()->length();
       
   470   for (int i = 0; i < len; ++i) {
       
   471     MethodPtr method = ik->methods()->at(i);
       
   472     if (_method_flag_predicate(method)) {
       
   473       SymbolEntryPtr entry = this->_artifacts->map_symbol(method->name());
       
   474       assert(entry != NULL, "invariant");
       
   475       if (_unique_predicate(entry->id())) {
       
   476         count += write__artifact__symbol__entry__(this->_writer, entry);
       
   477       }
       
   478       entry = this->_artifacts->map_symbol(method->signature());
       
   479       assert(entry != NULL, "invariant");
       
   480       if (_unique_predicate(entry->id())) {
       
   481         count += write__artifact__symbol__entry__(this->_writer, entry);
       
   482       }
       
   483     }
       
   484   }
       
   485   return count;
       
   486 }
       
   487 
       
   488 typedef KlassSymbolWriterImpl<LeakPredicate> LeakKlassSymbolWriterImpl;
       
   489 typedef JfrArtifactWriterHost<LeakKlassSymbolWriterImpl, TYPE_SYMBOL> LeakKlassSymbolWriter;
       
   490 
       
   491 class ClearKlassAndMethods {
       
   492  private:
       
   493   ClearArtifact<KlassPtr> _clear_klass_tag_bits;
       
   494   ClearArtifact<MethodPtr> _clear_method_flag;
       
   495   MethodUsedPredicate<false> _method_used_predicate;
       
   496 
       
   497  public:
       
   498   ClearKlassAndMethods(bool class_unload) : _clear_klass_tag_bits(class_unload),
       
   499                                             _clear_method_flag(class_unload),
       
   500                                             _method_used_predicate(class_unload) {}
       
   501   bool operator()(KlassPtr klass) {
       
   502     if (_method_used_predicate(klass)) {
       
   503       const InstanceKlass* ik = InstanceKlass::cast(klass);
       
   504       const int len = ik->methods()->length();
       
   505       for (int i = 0; i < len; ++i) {
       
   506         MethodPtr method = ik->methods()->at(i);
       
   507         _clear_method_flag(method);
       
   508       }
       
   509     }
       
   510     _clear_klass_tag_bits(klass);
       
   511     return true;
       
   512   }
       
   513 };
       
   514 
       
   515 typedef CompositeFunctor<KlassPtr,
       
   516                          TagLeakpKlassArtifact,
       
   517                          LeakKlassWriter> LeakpKlassArtifactTagging;
       
   518 
       
   519 typedef CompositeFunctor<KlassPtr,
       
   520                          LeakpKlassArtifactTagging,
       
   521                          KlassWriter> CompositeKlassWriter;
       
   522 
       
   523 typedef CompositeFunctor<KlassPtr,
       
   524                          CompositeKlassWriter,
       
   525                          KlassArtifactRegistrator> CompositeKlassWriterRegistration;
       
   526 
       
   527 typedef CompositeFunctor<KlassPtr,
       
   528                          KlassWriter,
       
   529                          KlassArtifactRegistrator> KlassWriterRegistration;
       
   530 
       
   531 typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
       
   532 typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
       
   533 
       
   534 /*
       
   535  * Composite operation
       
   536  *
       
   537  * TagLeakpKlassArtifact ->
       
   538  *   LeakpPredicate ->
       
   539  *     LeakpKlassWriter ->
       
   540  *       KlassPredicate ->
       
   541  *         KlassWriter ->
       
   542  *           KlassWriterRegistration
       
   543  */
       
   544 void JfrTypeSet::write_klass_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
       
   545   assert(!_artifacts->has_klass_entries(), "invariant");
       
   546   KlassArtifactRegistrator reg(_artifacts);
       
   547   KlassWriter kw(writer, _artifacts, _class_unload);
       
   548   KlassWriterRegistration kwr(&kw, &reg);
       
   549   if (leakp_writer == NULL) {
       
   550     KlassCallback callback(&kwr);
       
   551     _subsystem_callback = &callback;
       
   552     do_klasses();
       
   553     return;
       
   554   }
       
   555   TagLeakpKlassArtifact tagging(_class_unload);
       
   556   LeakKlassWriter lkw(leakp_writer, _artifacts, _class_unload);
       
   557   LeakpKlassArtifactTagging lpkat(&tagging, &lkw);
       
   558   CompositeKlassWriter ckw(&lpkat, &kw);
       
   559   CompositeKlassWriterRegistration ckwr(&ckw, &reg);
       
   560   CompositeKlassCallback callback(&ckwr);
       
   561   _subsystem_callback = &callback;
       
   562   do_klasses();
       
   563 }
       
   564 
       
   565 typedef CompositeFunctor<PkgPtr,
       
   566                          PackageWriter,
       
   567                          ClearArtifact<PkgPtr> > PackageWriterWithClear;
       
   568 
       
   569 typedef CompositeFunctor<PkgPtr,
       
   570                          LeakPackageWriter,
       
   571                          PackageWriter> CompositePackageWriter;
       
   572 
       
   573 typedef CompositeFunctor<PkgPtr,
       
   574                          CompositePackageWriter,
       
   575                          ClearArtifact<PkgPtr> > CompositePackageWriterWithClear;
       
   576 
       
   577 class PackageFieldSelector {
       
   578  public:
       
   579   typedef PkgPtr TypePtr;
       
   580   static TypePtr select(KlassPtr klass) {
       
   581     assert(klass != NULL, "invariant");
       
   582     return ((InstanceKlass*)klass)->package();
       
   583   }
       
   584 };
       
   585 
       
   586 typedef KlassToFieldEnvelope<PackageFieldSelector,
       
   587                              PackageWriterWithClear> KlassPackageWriterWithClear;
       
   588 
       
   589 typedef KlassToFieldEnvelope<PackageFieldSelector,
       
   590                              CompositePackageWriterWithClear> KlassCompositePackageWriterWithClear;
       
   591 
       
   592 typedef JfrArtifactCallbackHost<PkgPtr, PackageWriterWithClear> PackageCallback;
       
   593 typedef JfrArtifactCallbackHost<PkgPtr, CompositePackageWriterWithClear> CompositePackageCallback;
       
   594 
       
   595 /*
       
   596  * Composite operation
       
   597  *
       
   598  * LeakpPackageWriter ->
       
   599  *   PackageWriter ->
       
   600  *     ClearArtifact<PackageEntry>
       
   601  *
       
   602  */
       
   603 void JfrTypeSet::write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
       
   604   assert(_artifacts->has_klass_entries(), "invariant");
       
   605   ClearArtifact<PkgPtr> clear(_class_unload);
       
   606   PackageWriter pw(writer, _artifacts, _class_unload);
       
   607   if (leakp_writer == NULL) {
       
   608     PackageWriterWithClear pwwc(&pw, &clear);
       
   609     KlassPackageWriterWithClear kpwwc(&pwwc);
       
   610     _artifacts->iterate_klasses(kpwwc);
       
   611     PackageCallback callback(&pwwc);
       
   612     _subsystem_callback = &callback;
       
   613     do_packages();
       
   614     return;
       
   615   }
       
   616   LeakPackageWriter lpw(leakp_writer, _artifacts, _class_unload);
       
   617   CompositePackageWriter cpw(&lpw, &pw);
       
   618   CompositePackageWriterWithClear cpwwc(&cpw, &clear);
       
   619   KlassCompositePackageWriterWithClear ckpw(&cpwwc);
       
   620   _artifacts->iterate_klasses(ckpw);
       
   621   CompositePackageCallback callback(&cpwwc);
       
   622   _subsystem_callback = &callback;
       
   623   do_packages();
       
   624 }
       
   625 
       
   626 typedef CompositeFunctor<ModPtr,
       
   627                          ModuleWriter,
       
   628                          ClearArtifact<ModPtr> > ModuleWriterWithClear;
       
   629 
       
   630 typedef CompositeFunctor<ModPtr,
       
   631                          LeakModuleWriter,
       
   632                          ModuleWriter> CompositeModuleWriter;
       
   633 
       
   634 typedef CompositeFunctor<ModPtr,
       
   635                          CompositeModuleWriter,
       
   636                          ClearArtifact<ModPtr> > CompositeModuleWriterWithClear;
       
   637 
       
   638 typedef JfrArtifactCallbackHost<ModPtr, ModuleWriterWithClear> ModuleCallback;
       
   639 typedef JfrArtifactCallbackHost<ModPtr, CompositeModuleWriterWithClear> CompositeModuleCallback;
       
   640 
       
   641 class ModuleFieldSelector {
       
   642  public:
       
   643   typedef ModPtr TypePtr;
       
   644   static TypePtr select(KlassPtr klass) {
       
   645     assert(klass != NULL, "invariant");
       
   646     PkgPtr pkg = klass->package();
       
   647     return pkg != NULL ? pkg->module() : NULL;
       
   648   }
       
   649 };
       
   650 
       
   651 typedef KlassToFieldEnvelope<ModuleFieldSelector,
       
   652                              ModuleWriterWithClear> KlassModuleWriterWithClear;
       
   653 
       
   654 typedef KlassToFieldEnvelope<ModuleFieldSelector,
       
   655                              CompositeModuleWriterWithClear> KlassCompositeModuleWriterWithClear;
       
   656 
       
   657 /*
       
   658  * Composite operation
       
   659  *
       
   660  * LeakpModuleWriter ->
       
   661  *   ModuleWriter ->
       
   662  *     ClearArtifact<ModuleEntry>
       
   663  */
       
   664 void JfrTypeSet::write_module_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
       
   665   assert(_artifacts->has_klass_entries(), "invariant");
       
   666   ClearArtifact<ModPtr> clear(_class_unload);
       
   667   ModuleWriter mw(writer, _artifacts, _class_unload);
       
   668   if (leakp_writer == NULL) {
       
   669     ModuleWriterWithClear mwwc(&mw, &clear);
       
   670     KlassModuleWriterWithClear kmwwc(&mwwc);
       
   671     _artifacts->iterate_klasses(kmwwc);
       
   672     ModuleCallback callback(&mwwc);
       
   673     _subsystem_callback = &callback;
       
   674     do_modules();
       
   675     return;
       
   676   }
       
   677   LeakModuleWriter lmw(leakp_writer, _artifacts, _class_unload);
       
   678   CompositeModuleWriter cmw(&lmw, &mw);
       
   679   CompositeModuleWriterWithClear cmwwc(&cmw, &clear);
       
   680   KlassCompositeModuleWriterWithClear kmwwc(&cmwwc);
       
   681   _artifacts->iterate_klasses(kmwwc);
       
   682   CompositeModuleCallback callback(&cmwwc);
       
   683   _subsystem_callback = &callback;
       
   684   do_modules();
       
   685 }
       
   686 
       
   687 typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
       
   688 typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
       
   689 typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
       
   690 typedef JfrArtifactCallbackHost<CldPtr, CldWriterWithClear> CldCallback;
       
   691 typedef JfrArtifactCallbackHost<CldPtr, CompositeCldWriterWithClear> CompositeCldCallback;
       
   692 
       
   693 class CldFieldSelector {
       
   694  public:
       
   695   typedef CldPtr TypePtr;
       
   696   static TypePtr select(KlassPtr klass) {
       
   697     assert(klass != NULL, "invariant");
       
   698     CldPtr cld = klass->class_loader_data();
       
   699     return cld->is_anonymous() ? NULL : cld;
       
   700   }
       
   701 };
       
   702 
       
   703 typedef KlassToFieldEnvelope<CldFieldSelector, CldWriterWithClear> KlassCldWriterWithClear;
       
   704 typedef KlassToFieldEnvelope<CldFieldSelector, CompositeCldWriterWithClear> KlassCompositeCldWriterWithClear;
       
   705 
       
   706 /*
       
   707  * Composite operation
       
   708  *
       
   709  * LeakpClassLoaderWriter ->
       
   710  *   ClassLoaderWriter ->
       
   711  *     ClearArtifact<ClassLoaderData>
       
   712  */
       
   713 void JfrTypeSet::write_class_loader_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
       
   714   assert(_artifacts->has_klass_entries(), "invariant");
       
   715   ClearArtifact<CldPtr> clear(_class_unload);
       
   716   CldWriter cldw(writer, _artifacts, _class_unload);
       
   717   if (leakp_writer == NULL) {
       
   718     CldWriterWithClear cldwwc(&cldw, &clear);
       
   719     KlassCldWriterWithClear kcldwwc(&cldwwc);
       
   720     _artifacts->iterate_klasses(kcldwwc);
       
   721     CldCallback callback(&cldwwc);
       
   722     _subsystem_callback = &callback;
       
   723     do_class_loaders();
       
   724     return;
       
   725   }
       
   726   LeakCldWriter lcldw(leakp_writer, _artifacts, _class_unload);
       
   727   CompositeCldWriter ccldw(&lcldw, &cldw);
       
   728   CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
       
   729   KlassCompositeCldWriterWithClear kcclwwc(&ccldwwc);
       
   730   _artifacts->iterate_klasses(kcclwwc);
       
   731   CompositeCldCallback callback(&ccldwwc);
       
   732   _subsystem_callback = &callback;
       
   733   do_class_loaders();
       
   734 }
       
   735 
       
   736 template <bool predicate_bool, typename MethodFunctor>
       
   737 class MethodIteratorHost {
       
   738  private:
       
   739   MethodFunctor _method_functor;
       
   740   MethodUsedPredicate<predicate_bool> _method_used_predicate;
       
   741   MethodFlagPredicate _method_flag_predicate;
       
   742 
       
   743  public:
       
   744   MethodIteratorHost(JfrCheckpointWriter* writer,
       
   745                      JfrArtifactSet* artifacts,
       
   746                      bool class_unload,
       
   747                      bool skip_header = false) :
       
   748     _method_functor(writer, artifacts, class_unload, skip_header),
       
   749     _method_used_predicate(class_unload),
       
   750     _method_flag_predicate(class_unload) {}
       
   751 
       
   752   bool operator()(KlassPtr klass) {
       
   753     if (_method_used_predicate(klass)) {
       
   754       assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
       
   755       const InstanceKlass* ik = InstanceKlass::cast(klass);
       
   756       const int len = ik->methods()->length();
       
   757       for (int i = 0; i < len; ++i) {
       
   758         MethodPtr method = ik->methods()->at(i);
       
   759         if (_method_flag_predicate(method)) {
       
   760           _method_functor(method);
       
   761         }
       
   762       }
       
   763     }
       
   764     return true;
       
   765   }
       
   766 
       
   767   int count() const { return _method_functor.count(); }
       
   768   void add(int count) { _method_functor.add(count); }
       
   769 };
       
   770 
       
   771 typedef MethodIteratorHost<true /*leakp */,  MethodWriterImpl> LeakMethodWriter;
       
   772 typedef MethodIteratorHost<false, MethodWriterImpl> MethodWriter;
       
   773 typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
       
   774 
       
   775 /*
       
   776  * Composite operation
       
   777  *
       
   778  * LeakpMethodWriter ->
       
   779  *   MethodWriter
       
   780  */
       
   781 void JfrTypeSet::write_method_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
       
   782   assert(_artifacts->has_klass_entries(), "invariant");
       
   783   MethodWriter mw(writer, _artifacts, _class_unload);
       
   784   if (leakp_writer == NULL) {
       
   785     _artifacts->iterate_klasses(mw);
       
   786     return;
       
   787   }
       
   788   LeakMethodWriter lpmw(leakp_writer, _artifacts, _class_unload);
       
   789   CompositeMethodWriter cmw(&lpmw, &mw);
       
   790   _artifacts->iterate_klasses(cmw);
       
   791 }
       
   792 static void write_symbols_leakp(JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
       
   793   assert(leakp_writer != NULL, "invariant");
       
   794   assert(artifacts != NULL, "invariant");
       
   795   LeakKlassSymbolWriter lpksw(leakp_writer, artifacts, class_unload);
       
   796   artifacts->iterate_klasses(lpksw);
       
   797 }
       
   798 static void write_symbols(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
       
   799   assert(writer != NULL, "invariant");
       
   800   assert(artifacts != NULL, "invariant");
       
   801   if (leakp_writer != NULL) {
       
   802     write_symbols_leakp(leakp_writer, artifacts, class_unload);
       
   803   }
       
   804   // iterate all registered symbols
       
   805   SymbolEntryWriter symbol_writer(writer, artifacts, class_unload);
       
   806   artifacts->iterate_symbols(symbol_writer);
       
   807   CStringEntryWriter cstring_writer(writer, artifacts, class_unload, true); // skip header
       
   808   artifacts->iterate_cstrings(cstring_writer);
       
   809   symbol_writer.add(cstring_writer.count());
       
   810 }
       
   811 
       
   812 bool JfrTypeSet::_class_unload = false;
       
   813 JfrArtifactSet* JfrTypeSet::_artifacts = NULL;
       
   814 JfrArtifactClosure* JfrTypeSet::_subsystem_callback = NULL;
       
   815 
       
   816 void JfrTypeSet::write_symbol_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
       
   817   assert(writer != NULL, "invariant");
       
   818   assert(_artifacts->has_klass_entries(), "invariant");
       
   819   write_symbols(writer, leakp_writer, _artifacts, _class_unload);
       
   820 }
       
   821 
       
   822 void JfrTypeSet::do_unloaded_klass(Klass* klass) {
       
   823   assert(klass != NULL, "invariant");
       
   824   assert(_subsystem_callback != NULL, "invariant");
       
   825   if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) {
       
   826     JfrEventClasses::increment_unloaded_event_class();
       
   827   }
       
   828   if (USED_THIS_EPOCH(klass)) { // includes leakp subset
       
   829     _subsystem_callback->do_artifact(klass);
       
   830     return;
       
   831   }
       
   832   if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
       
   833     SET_LEAKP_USED_THIS_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
       
   834     _subsystem_callback->do_artifact(klass);
       
   835   }
       
   836 }
       
   837 
       
   838 void JfrTypeSet::do_klass(Klass* klass) {
       
   839   assert(klass != NULL, "invariant");
       
   840   assert(_subsystem_callback != NULL, "invariant");
       
   841   if (USED_PREV_EPOCH(klass)) { // includes leakp subset
       
   842     _subsystem_callback->do_artifact(klass);
       
   843     return;
       
   844   }
       
   845   if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
       
   846     SET_LEAKP_USED_PREV_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
       
   847     _subsystem_callback->do_artifact(klass);
       
   848   }
       
   849 }
       
   850 
       
   851 void JfrTypeSet::do_klasses() {
       
   852   if (_class_unload) {
       
   853     ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass);
       
   854     return;
       
   855   }
       
   856   ClassLoaderDataGraph::classes_do(&do_klass);
       
   857 }
       
   858 
       
   859 void JfrTypeSet::do_unloaded_package(PackageEntry* entry) {
       
   860   assert(entry != NULL, "invariant");
       
   861   assert(_subsystem_callback != NULL, "invariant");
       
   862   if (ANY_USED_THIS_EPOCH(entry)) { // includes leakp subset
       
   863     _subsystem_callback->do_artifact(entry);
       
   864   }
       
   865 }
       
   866 
       
   867 void JfrTypeSet::do_package(PackageEntry* entry) {
       
   868   assert(_subsystem_callback != NULL, "invariant");
       
   869   if (ANY_USED_PREV_EPOCH(entry)) { // includes leakp subset
       
   870     _subsystem_callback->do_artifact(entry);
       
   871   }
       
   872 }
       
   873 
       
   874 void JfrTypeSet::do_packages() {
       
   875   if (_class_unload) {
       
   876     ClassLoaderDataGraph::packages_unloading_do(&do_unloaded_package);
       
   877     return;
       
   878   }
       
   879   ClassLoaderDataGraph::packages_do(&do_package);
       
   880 }
       
   881 void JfrTypeSet::do_unloaded_module(ModuleEntry* entry) {
       
   882   assert(entry != NULL, "invariant");
       
   883   assert(_subsystem_callback != NULL, "invariant");
       
   884   if (ANY_USED_THIS_EPOCH(entry)) { // includes leakp subset
       
   885     _subsystem_callback->do_artifact(entry);
       
   886   }
       
   887 }
       
   888 
       
   889 void JfrTypeSet::do_module(ModuleEntry* entry) {
       
   890   assert(_subsystem_callback != NULL, "invariant");
       
   891   if (ANY_USED_PREV_EPOCH(entry)) { // includes leakp subset
       
   892     _subsystem_callback->do_artifact(entry);
       
   893   }
       
   894 }
       
   895 
       
   896 void JfrTypeSet::do_modules() {
       
   897   if (_class_unload) {
       
   898     ClassLoaderDataGraph::modules_unloading_do(&do_unloaded_module);
       
   899     return;
       
   900   }
       
   901   ClassLoaderDataGraph::modules_do(&do_module);
       
   902 }
       
   903 
       
   904 void JfrTypeSet::do_unloaded_class_loader_data(ClassLoaderData* cld) {
       
   905   assert(_subsystem_callback != NULL, "invariant");
       
   906   if (ANY_USED_THIS_EPOCH(cld)) { // includes leakp subset
       
   907     _subsystem_callback->do_artifact(cld);
       
   908   }
       
   909 }
       
   910 
       
   911 void JfrTypeSet::do_class_loader_data(ClassLoaderData* cld) {
       
   912   assert(_subsystem_callback != NULL, "invariant");
       
   913   if (ANY_USED_PREV_EPOCH(cld)) { // includes leakp subset
       
   914     _subsystem_callback->do_artifact(cld);
       
   915   }
       
   916 }
       
   917 
       
   918 class CLDCallback : public CLDClosure {
       
   919  private:
       
   920   bool _class_unload;
       
   921  public:
       
   922   CLDCallback(bool class_unload) : _class_unload(class_unload) {}
       
   923   void do_cld(ClassLoaderData* cld) {
       
   924      assert(cld != NULL, "invariant");
       
   925     if (cld->is_anonymous()) {
       
   926       return;
       
   927     }
       
   928     if (_class_unload) {
       
   929       JfrTypeSet::do_unloaded_class_loader_data(cld);
       
   930       return;
       
   931     }
       
   932     JfrTypeSet::do_class_loader_data(cld);
       
   933   }
       
   934 };
       
   935 
       
   936 void JfrTypeSet::do_class_loaders() {
       
   937   CLDCallback cld_cb(_class_unload);
       
   938   if (_class_unload) {
       
   939     ClassLoaderDataGraph::cld_unloading_do(&cld_cb);
       
   940     return;
       
   941   }
       
   942   ClassLoaderDataGraph::cld_do(&cld_cb);
       
   943 }
       
   944 
       
   945 static void clear_artifacts(JfrArtifactSet* artifacts,
       
   946                             bool class_unload) {
       
   947   assert(artifacts != NULL, "invariant");
       
   948   assert(artifacts->has_klass_entries(), "invariant");
       
   949 
       
   950   // untag
       
   951   ClearKlassAndMethods clear(class_unload);
       
   952   artifacts->iterate_klasses(clear);
       
   953   artifacts->clear();
       
   954 }
       
   955 
       
   956 /**
       
   957  * Write all "tagged" (in-use) constant artifacts and their dependencies.
       
   958  */
       
   959 void JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload) {
       
   960   assert(writer != NULL, "invariant");
       
   961   ResourceMark rm;
       
   962   // initialization begin
       
   963   _class_unload = class_unload;
       
   964   ++checkpoint_id;
       
   965   if (_artifacts == NULL) {
       
   966     _artifacts = new JfrArtifactSet(class_unload);
       
   967     _subsystem_callback = NULL;
       
   968   } else {
       
   969     _artifacts->initialize(class_unload);
       
   970     _subsystem_callback = NULL;
       
   971   }
       
   972   assert(_artifacts != NULL, "invariant");
       
   973   assert(!_artifacts->has_klass_entries(), "invariant");
       
   974   assert(_subsystem_callback == NULL, "invariant");
       
   975   // initialization complete
       
   976 
       
   977   // write order is important because an individual write step
       
   978   // might tag an artifact to be written in a subsequent step
       
   979   write_klass_constants(writer, leakp_writer);
       
   980   if (_artifacts->has_klass_entries()) {
       
   981     write_package_constants(writer, leakp_writer);
       
   982     write_module_constants(writer, leakp_writer);
       
   983     write_class_loader_constants(writer, leakp_writer);
       
   984     write_method_constants(writer, leakp_writer);
       
   985     write_symbol_constants(writer, leakp_writer);
       
   986     clear_artifacts(_artifacts, class_unload);
       
   987   }
       
   988 }