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->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       BOOTSTRAP_LOADER_NAME,
 445       BOOTSTRAP_LOADER_NAME_LEN) == 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->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 }