1 /*
   2  * Copyright (c) 2016, 2020, 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/classLoaderDataGraph.hpp"
  27 #include "classfile/javaClasses.inline.hpp"
  28 #include "classfile/moduleEntry.hpp"
  29 #include "classfile/packageEntry.hpp"
  30 #include "classfile/symbolTable.hpp"
  31 #include "jfr/jfr.hpp"
  32 #include "jfr/jni/jfrGetAllEventClasses.hpp"
  33 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
  34 #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
  35 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
  36 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
  37 #include "jfr/utilities/jfrHashtable.hpp"
  38 #include "jfr/utilities/jfrTypes.hpp"
  39 #include "jfr/writers/jfrTypeWriterHost.hpp"
  40 #include "memory/iterator.hpp"
  41 #include "memory/resourceArea.hpp"
  42 #include "oops/instanceKlass.hpp"
  43 #include "oops/objArrayKlass.hpp"
  44 #include "oops/oop.inline.hpp"
  45 #include "utilities/accessFlags.hpp"
  46 #include "utilities/bitMap.inline.hpp"
  47 
  48 typedef const Klass* KlassPtr;
  49 typedef const PackageEntry* PkgPtr;
  50 typedef const ModuleEntry* ModPtr;
  51 typedef const ClassLoaderData* CldPtr;
  52 typedef const Method* MethodPtr;
  53 typedef const Symbol* SymbolPtr;
  54 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
  55 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
  56 
  57 static JfrCheckpointWriter* _writer = NULL;
  58 static JfrCheckpointWriter* _leakp_writer = NULL;
  59 static JfrArtifactSet* _artifacts = NULL;
  60 static JfrArtifactClosure* _subsystem_callback = NULL;
  61 static bool _class_unload = false;
  62 static bool _flushpoint = false;
  63 
  64 // incremented on each rotation
  65 static u8 checkpoint_id = 1;
  66 
  67 // creates a unique id by combining a checkpoint relative symbol id (2^24)
  68 // with the current checkpoint id (2^40)
  69 #define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))
  70 
  71 static traceid create_symbol_id(traceid artifact_id) {
  72   return artifact_id != 0 ? CREATE_SYMBOL_ID(artifact_id) : 0;
  73 }
  74 
  75 static bool current_epoch() {
  76   return _class_unload || _flushpoint;
  77 }
  78 
  79 static bool previous_epoch() {
  80   return !current_epoch();
  81 }
  82 
  83 static bool is_complete() {
  84   return !_artifacts->has_klass_entries() && current_epoch();
  85 }
  86 
  87 static traceid mark_symbol(KlassPtr klass, bool leakp) {
  88   return klass != NULL ? create_symbol_id(_artifacts->mark(klass, leakp)) : 0;
  89 }
  90 
  91 static traceid mark_symbol(Symbol* symbol, bool leakp) {
  92   return symbol != NULL ? create_symbol_id(_artifacts->mark(symbol, leakp)) : 0;
  93 }
  94 
  95 static traceid get_bootstrap_name(bool leakp) {
  96   return create_symbol_id(_artifacts->bootstrap_name(leakp));
  97 }
  98 
  99 template <typename T>
 100 static traceid artifact_id(const T* ptr) {
 101   assert(ptr != NULL, "invariant");
 102   return TRACE_ID(ptr);
 103 }
 104 
 105 static traceid package_id(KlassPtr klass, bool leakp) {
 106   assert(klass != NULL, "invariant");
 107   PkgPtr pkg_entry = klass->package();
 108   if (pkg_entry == NULL) {
 109     return 0;
 110   }
 111   if (leakp) {
 112     SET_LEAKP(pkg_entry);
 113   }
 114   // package implicitly tagged already
 115   return artifact_id(pkg_entry);
 116 }
 117 
 118 static traceid module_id(PkgPtr pkg, bool leakp) {
 119   assert(pkg != NULL, "invariant");
 120   ModPtr module_entry = pkg->module();
 121   if (module_entry == NULL) {
 122     return 0;
 123   }
 124   if (leakp) {
 125     SET_LEAKP(module_entry);
 126   } else {
 127     SET_TRANSIENT(module_entry);
 128   }
 129   return artifact_id(module_entry);
 130 }
 131 
 132 static traceid method_id(KlassPtr klass, MethodPtr method) {
 133   assert(klass != NULL, "invariant");
 134   assert(method != NULL, "invariant");
 135   return METHOD_ID(klass, method);
 136 }
 137 
 138 static traceid cld_id(CldPtr cld, bool leakp) {
 139   assert(cld != NULL, "invariant");
 140   if (leakp) {
 141     SET_LEAKP(cld);
 142   } else {
 143     SET_TRANSIENT(cld);
 144   }
 145   return artifact_id(cld);
 146 }
 147 
 148 template <typename T>
 149 static s4 get_flags(const T* ptr) {
 150   assert(ptr != NULL, "invariant");
 151   return ptr->access_flags().get_flags();
 152 }
 153 
 154 static bool is_unsafe_anonymous(const Klass* klass) {
 155   assert(klass != NULL, "invariant");
 156   assert(!klass->is_objArray_klass(), "invariant");
 157   return klass->is_instance_klass() && InstanceKlass::cast(klass)->is_unsafe_anonymous();
 158 }
 159 
 160 static ClassLoaderData* get_cld(const Klass* klass) {
 161   assert(klass != NULL, "invariant");
 162   if (klass->is_objArray_klass()) {
 163     klass = ObjArrayKlass::cast(klass)->bottom_klass();
 164   }
 165   if (klass->is_non_strong_hidden()) return NULL;
 166   return is_unsafe_anonymous(klass) ?
 167     InstanceKlass::cast(klass)->unsafe_anonymous_host()->class_loader_data() : klass->class_loader_data();
 168 }
 169 
 170 template <typename T>
 171 static void set_serialized(const T* ptr) {
 172   assert(ptr != NULL, "invariant");
 173   SET_SERIALIZED(ptr);
 174   assert(IS_SERIALIZED(ptr), "invariant");
 175   CLEAR_THIS_EPOCH_CLEARED_BIT(ptr);
 176 }
 177 
 178 /*
 179  * In C++03, functions used as template parameters must have external linkage;
 180  * this restriction was removed in C++11. Change back to "static" and
 181  * rename functions when C++11 becomes available.
 182  *
 183  * The weird naming is an effort to decrease the risk of name clashes.
 184  */
 185 
 186 static int write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp) {
 187   assert(writer != NULL, "invariant");
 188   assert(_artifacts != NULL, "invariant");
 189   assert(klass != NULL, "invariant");
 190   writer->write(artifact_id(klass));
 191   ClassLoaderData* cld = get_cld(klass);
 192   writer->write(cld != NULL ? cld_id(cld, leakp) : 0);
 193   writer->write(mark_symbol(klass, leakp));
 194   writer->write(package_id(klass, leakp));
 195   writer->write(get_flags(klass));
 196   writer->write<bool>(klass->is_hidden());
 197   return 1;
 198 }
 199 
 200 int write__klass(JfrCheckpointWriter* writer, const void* k) {
 201   assert(k != NULL, "invariant");
 202   KlassPtr klass = (KlassPtr)k;
 203   set_serialized(klass);
 204   return write_klass(writer, klass, false);
 205 }
 206 
 207 int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) {
 208   assert(k != NULL, "invariant");
 209   KlassPtr klass = (KlassPtr)k;
 210   return write_klass(writer, klass, true);
 211 }
 212 
 213 static bool is_implied(const Klass* klass) {
 214   assert(klass != NULL, "invariant");
 215   return klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass();
 216 }
 217 
 218 static void do_implied(Klass* klass) {
 219   assert(klass != NULL, "invariant");
 220   if (is_implied(klass)) {
 221     if (_leakp_writer != NULL) {
 222       SET_LEAKP(klass);
 223     }
 224     _subsystem_callback->do_artifact(klass);
 225   }
 226 }
 227 
 228 static void do_unloaded_klass(Klass* klass) {
 229   assert(klass != NULL, "invariant");
 230   assert(_subsystem_callback != NULL, "invariant");
 231   if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) {
 232     JfrEventClasses::increment_unloaded_event_class();
 233   }
 234   if (USED_THIS_EPOCH(klass)) {
 235     ObjectSampleCheckpoint::on_klass_unload(klass);
 236     _subsystem_callback->do_artifact(klass);
 237     return;
 238   }
 239   do_implied(klass);
 240 }
 241 
 242 static void do_klass(Klass* klass) {
 243   assert(klass != NULL, "invariant");
 244   assert(_subsystem_callback != NULL, "invariant");
 245   if (_flushpoint) {
 246     if (USED_THIS_EPOCH(klass)) {
 247       _subsystem_callback->do_artifact(klass);
 248       return;
 249     }
 250   } else {
 251     if (USED_PREV_EPOCH(klass)) {
 252       _subsystem_callback->do_artifact(klass);
 253       return;
 254     }
 255   }
 256   do_implied(klass);
 257 }
 258 
 259 static void do_klasses() {
 260   if (_class_unload) {
 261     ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass);
 262     return;
 263   }
 264   ClassLoaderDataGraph::classes_do(&do_klass);
 265 }
 266 
 267 typedef SerializePredicate<KlassPtr> KlassPredicate;
 268 typedef JfrPredicatedTypeWriterImplHost<KlassPtr, KlassPredicate, write__klass> KlassWriterImpl;
 269 typedef JfrTypeWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
 270 typedef CompositeFunctor<KlassPtr, KlassWriter, KlassArtifactRegistrator> KlassWriterRegistration;
 271 typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
 272 
 273 template <>
 274 class LeakPredicate<const Klass*> {
 275 public:
 276   LeakPredicate(bool class_unload) {}
 277   bool operator()(const Klass* klass) {
 278     assert(klass != NULL, "invariant");
 279     return IS_LEAKP(klass) || is_implied(klass);
 280   }
 281 };
 282 
 283 typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
 284 typedef JfrPredicatedTypeWriterImplHost<KlassPtr, LeakKlassPredicate, write__klass__leakp> LeakKlassWriterImpl;
 285 typedef JfrTypeWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
 286 
 287 typedef CompositeFunctor<KlassPtr, LeakKlassWriter, KlassWriter> CompositeKlassWriter;
 288 typedef CompositeFunctor<KlassPtr, CompositeKlassWriter, KlassArtifactRegistrator> CompositeKlassWriterRegistration;
 289 typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
 290 
 291 static bool write_klasses() {
 292   assert(!_artifacts->has_klass_entries(), "invariant");
 293   assert(_writer != NULL, "invariant");
 294   KlassArtifactRegistrator reg(_artifacts);
 295   KlassWriter kw(_writer, _class_unload);
 296   KlassWriterRegistration kwr(&kw, &reg);
 297   if (_leakp_writer == NULL) {
 298     KlassCallback callback(&kwr);
 299     _subsystem_callback = &callback;
 300     do_klasses();
 301   } else {
 302     LeakKlassWriter lkw(_leakp_writer, _class_unload);
 303     CompositeKlassWriter ckw(&lkw, &kw);
 304     CompositeKlassWriterRegistration ckwr(&ckw, &reg);
 305     CompositeKlassCallback callback(&ckwr);
 306     _subsystem_callback = &callback;
 307     do_klasses();
 308   }
 309   if (is_complete()) {
 310     return false;
 311   }
 312   _artifacts->tally(kw);
 313   return true;
 314 }
 315 
 316 template <typename T>
 317 static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) {
 318   assert(callback != NULL, "invariant");
 319   assert(value != NULL, "invariant");
 320   if (USED_PREV_EPOCH(value)) {
 321     callback->do_artifact(value);
 322     assert(IS_NOT_SERIALIZED(value), "invariant");
 323     return;
 324   }
 325   if (IS_SERIALIZED(value)) {
 326     CLEAR_SERIALIZED(value);
 327   }
 328   assert(IS_NOT_SERIALIZED(value), "invariant");
 329 }
 330 
 331 typedef JfrArtifactCallbackHost<KlassPtr, KlassArtifactRegistrator> RegistrationCallback;
 332 
 333 static void register_klass(Klass* klass) {
 334   assert(klass != NULL, "invariant");
 335   assert(_subsystem_callback != NULL, "invariant");
 336   do_previous_epoch_artifact(_subsystem_callback, klass);
 337 }
 338 
 339 static void do_register_klasses() {
 340   ClassLoaderDataGraph::classes_do(&register_klass);
 341 }
 342 
 343 static void register_klasses() {
 344   assert(!_artifacts->has_klass_entries(), "invariant");
 345   KlassArtifactRegistrator reg(_artifacts);
 346   RegistrationCallback callback(&reg);
 347   _subsystem_callback = &callback;
 348   do_register_klasses();
 349 }
 350 
 351 static int write_package(JfrCheckpointWriter* writer, PkgPtr pkg, bool leakp) {
 352   assert(writer != NULL, "invariant");
 353   assert(_artifacts != NULL, "invariant");
 354   assert(pkg != NULL, "invariant");
 355   writer->write(artifact_id(pkg));
 356   writer->write(mark_symbol(pkg->name(), leakp));
 357   writer->write(module_id(pkg, leakp));
 358   writer->write((bool)pkg->is_exported());
 359   return 1;
 360 }
 361 
 362 int write__package(JfrCheckpointWriter* writer, const void* p) {
 363   assert(p != NULL, "invariant");
 364   PkgPtr pkg = (PkgPtr)p;
 365   set_serialized(pkg);
 366   return write_package(writer, pkg, false);
 367 }
 368 
 369 int write__package__leakp(JfrCheckpointWriter* writer, const void* p) {
 370   assert(p != NULL, "invariant");
 371   PkgPtr pkg = (PkgPtr)p;
 372   CLEAR_LEAKP(pkg);
 373   return write_package(writer, pkg, true);
 374 }
 375 
 376 static void do_package(PackageEntry* entry) {
 377   do_previous_epoch_artifact(_subsystem_callback, entry);
 378 }
 379 
 380 static void do_packages() {
 381   ClassLoaderDataGraph::packages_do(&do_package);
 382 }
 383 
 384 class PackageFieldSelector {
 385  public:
 386   typedef PkgPtr TypePtr;
 387   static TypePtr select(KlassPtr klass) {
 388     assert(klass != NULL, "invariant");
 389     return klass->package();
 390   }
 391 };
 392 
 393 typedef SerializePredicate<PkgPtr> PackagePredicate;
 394 typedef JfrPredicatedTypeWriterImplHost<PkgPtr, PackagePredicate, write__package> PackageWriterImpl;
 395 typedef JfrTypeWriterHost<PackageWriterImpl, TYPE_PACKAGE> PackageWriter;
 396 typedef CompositeFunctor<PkgPtr, PackageWriter, ClearArtifact<PkgPtr> > PackageWriterWithClear;
 397 typedef KlassToFieldEnvelope<PackageFieldSelector, PackageWriter> KlassPackageWriter;
 398 typedef JfrArtifactCallbackHost<PkgPtr, PackageWriterWithClear> PackageCallback;
 399 
 400 typedef LeakPredicate<PkgPtr> LeakPackagePredicate;
 401 typedef JfrPredicatedTypeWriterImplHost<PkgPtr, LeakPackagePredicate, write__package__leakp> LeakPackageWriterImpl;
 402 typedef JfrTypeWriterHost<LeakPackageWriterImpl, TYPE_PACKAGE> LeakPackageWriter;
 403 
 404 typedef CompositeFunctor<PkgPtr, LeakPackageWriter, PackageWriter> CompositePackageWriter;
 405 typedef KlassToFieldEnvelope<PackageFieldSelector, CompositePackageWriter> KlassCompositePackageWriter;
 406 typedef KlassToFieldEnvelope<PackageFieldSelector, PackageWriterWithClear> KlassPackageWriterWithClear;
 407 typedef CompositeFunctor<PkgPtr, CompositePackageWriter, ClearArtifact<PkgPtr> > CompositePackageWriterWithClear;
 408 typedef JfrArtifactCallbackHost<PkgPtr, CompositePackageWriterWithClear> CompositePackageCallback;
 409 
 410 static void write_packages() {
 411   assert(_writer != NULL, "invariant");
 412   PackageWriter pw(_writer, _class_unload);
 413   KlassPackageWriter kpw(&pw);
 414   if (current_epoch()) {
 415     _artifacts->iterate_klasses(kpw);
 416     _artifacts->tally(pw);
 417     return;
 418   }
 419   assert(previous_epoch(), "invariant");
 420   if (_leakp_writer == NULL) {
 421     _artifacts->iterate_klasses(kpw);
 422     ClearArtifact<PkgPtr> clear;
 423     PackageWriterWithClear pwwc(&pw, &clear);
 424     PackageCallback callback(&pwwc);
 425     _subsystem_callback = &callback;
 426     do_packages();
 427   } else {
 428     LeakPackageWriter lpw(_leakp_writer, _class_unload);
 429     CompositePackageWriter cpw(&lpw, &pw);
 430     KlassCompositePackageWriter kcpw(&cpw);
 431     _artifacts->iterate_klasses(kcpw);
 432     ClearArtifact<PkgPtr> clear;
 433     CompositePackageWriterWithClear cpwwc(&cpw, &clear);
 434     CompositePackageCallback callback(&cpwwc);
 435     _subsystem_callback = &callback;
 436     do_packages();
 437   }
 438   _artifacts->tally(pw);
 439 }
 440 
 441 typedef JfrArtifactCallbackHost<PkgPtr, ClearArtifact<PkgPtr> > ClearPackageCallback;
 442 
 443 static void clear_packages() {
 444   ClearArtifact<PkgPtr> clear;
 445   ClearPackageCallback callback(&clear);
 446   _subsystem_callback = &callback;
 447   do_packages();
 448 }
 449 
 450 static int write_module(JfrCheckpointWriter* writer, ModPtr mod, bool leakp) {
 451   assert(mod != NULL, "invariant");
 452   assert(_artifacts != NULL, "invariant");
 453   writer->write(artifact_id(mod));
 454   writer->write(mark_symbol(mod->name(), leakp));
 455   writer->write(mark_symbol(mod->version(), leakp));
 456   writer->write(mark_symbol(mod->location(), leakp));
 457   writer->write(cld_id(mod->loader_data(), leakp));
 458   return 1;
 459 }
 460 
 461 int write__module(JfrCheckpointWriter* writer, const void* m) {
 462   assert(m != NULL, "invariant");
 463   ModPtr mod = (ModPtr)m;
 464   set_serialized(mod);
 465   return write_module(writer, mod, false);
 466 }
 467 
 468 int write__module__leakp(JfrCheckpointWriter* writer, const void* m) {
 469   assert(m != NULL, "invariant");
 470   ModPtr mod = (ModPtr)m;
 471   CLEAR_LEAKP(mod);
 472   return write_module(writer, mod, true);
 473 }
 474 
 475 static void do_module(ModuleEntry* entry) {
 476   do_previous_epoch_artifact(_subsystem_callback, entry);
 477 }
 478 
 479 static void do_modules() {
 480   ClassLoaderDataGraph::modules_do(&do_module);
 481 }
 482 
 483 class ModuleFieldSelector {
 484  public:
 485   typedef ModPtr TypePtr;
 486   static TypePtr select(KlassPtr klass) {
 487     assert(klass != NULL, "invariant");
 488     PkgPtr pkg = klass->package();
 489     return pkg != NULL ? pkg->module() : NULL;
 490   }
 491 };
 492 
 493 typedef SerializePredicate<ModPtr> ModulePredicate;
 494 typedef JfrPredicatedTypeWriterImplHost<ModPtr, ModulePredicate, write__module> ModuleWriterImpl;
 495 typedef JfrTypeWriterHost<ModuleWriterImpl, TYPE_MODULE> ModuleWriter;
 496 typedef CompositeFunctor<ModPtr, ModuleWriter, ClearArtifact<ModPtr> > ModuleWriterWithClear;
 497 typedef JfrArtifactCallbackHost<ModPtr, ModuleWriterWithClear> ModuleCallback;
 498 typedef KlassToFieldEnvelope<ModuleFieldSelector, ModuleWriter> KlassModuleWriter;
 499 
 500 typedef LeakPredicate<ModPtr> LeakModulePredicate;
 501 typedef JfrPredicatedTypeWriterImplHost<ModPtr, LeakModulePredicate, write__module__leakp> LeakModuleWriterImpl;
 502 typedef JfrTypeWriterHost<LeakModuleWriterImpl, TYPE_MODULE> LeakModuleWriter;
 503 
 504 typedef CompositeFunctor<ModPtr, LeakModuleWriter, ModuleWriter> CompositeModuleWriter;
 505 typedef KlassToFieldEnvelope<ModuleFieldSelector, CompositeModuleWriter> KlassCompositeModuleWriter;
 506 typedef CompositeFunctor<ModPtr, CompositeModuleWriter, ClearArtifact<ModPtr> > CompositeModuleWriterWithClear;
 507 typedef JfrArtifactCallbackHost<ModPtr, CompositeModuleWriterWithClear> CompositeModuleCallback;
 508 
 509 static void write_modules() {
 510   assert(_writer != NULL, "invariant");
 511   ModuleWriter mw(_writer, _class_unload);
 512   KlassModuleWriter kmw(&mw);
 513   if (current_epoch()) {
 514     _artifacts->iterate_klasses(kmw);
 515     _artifacts->tally(mw);
 516     return;
 517   }
 518   assert(previous_epoch(), "invariant");
 519   if (_leakp_writer == NULL) {
 520     _artifacts->iterate_klasses(kmw);
 521     ClearArtifact<ModPtr> clear;
 522     ModuleWriterWithClear mwwc(&mw, &clear);
 523     ModuleCallback callback(&mwwc);
 524     _subsystem_callback = &callback;
 525     do_modules();
 526   } else {
 527     LeakModuleWriter lmw(_leakp_writer, _class_unload);
 528     CompositeModuleWriter cmw(&lmw, &mw);
 529     KlassCompositeModuleWriter kcpw(&cmw);
 530     _artifacts->iterate_klasses(kcpw);
 531     ClearArtifact<ModPtr> clear;
 532     CompositeModuleWriterWithClear cmwwc(&cmw, &clear);
 533     CompositeModuleCallback callback(&cmwwc);
 534     _subsystem_callback = &callback;
 535     do_modules();
 536   }
 537   _artifacts->tally(mw);
 538 }
 539 
 540 typedef JfrArtifactCallbackHost<ModPtr, ClearArtifact<ModPtr> > ClearModuleCallback;
 541 
 542 static void clear_modules() {
 543   ClearArtifact<ModPtr> clear;
 544   ClearModuleCallback callback(&clear);
 545   _subsystem_callback = &callback;
 546   do_modules();
 547 }
 548 
 549 static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) {
 550   assert(cld != NULL, "invariant");
 551   // class loader type
 552   const Klass* class_loader_klass = cld->class_loader_klass();
 553   if (class_loader_klass == NULL) {
 554     // (primordial) boot class loader
 555     writer->write(artifact_id(cld)); // class loader instance id
 556     writer->write((traceid)0);  // class loader type id (absence of)
 557     writer->write(get_bootstrap_name(leakp)); // maps to synthetic name -> "bootstrap"
 558   } else {
 559     writer->write(artifact_id(cld)); // class loader instance id
 560     writer->write(artifact_id(class_loader_klass)); // class loader type id
 561     writer->write(mark_symbol(cld->name(), leakp)); // class loader instance name
 562   }
 563   return 1;
 564 }
 565 
 566 int write__classloader(JfrCheckpointWriter* writer, const void* c) {
 567   assert(c != NULL, "invariant");
 568   CldPtr cld = (CldPtr)c;
 569   set_serialized(cld);
 570   return write_classloader(writer, cld, false);
 571 }
 572 
 573 int write__classloader__leakp(JfrCheckpointWriter* writer, const void* c) {
 574   assert(c != NULL, "invariant");
 575   CldPtr cld = (CldPtr)c;
 576   CLEAR_LEAKP(cld);
 577   return write_classloader(writer, cld, true);
 578 }
 579 
 580 static void do_class_loader_data(ClassLoaderData* cld) {
 581   do_previous_epoch_artifact(_subsystem_callback, cld);
 582 }
 583 
 584 class KlassCldFieldSelector {
 585  public:
 586   typedef CldPtr TypePtr;
 587   static TypePtr select(KlassPtr klass) {
 588     assert(klass != NULL, "invariant");
 589     return get_cld(klass);
 590   }
 591 };
 592 
 593 class ModuleCldFieldSelector {
 594 public:
 595   typedef CldPtr TypePtr;
 596   static TypePtr select(KlassPtr klass) {
 597     assert(klass != NULL, "invariant");
 598     ModPtr mod = ModuleFieldSelector::select(klass);
 599     return mod != NULL ? mod->loader_data() : NULL;
 600   }
 601 };
 602 
 603 class CLDCallback : public CLDClosure {
 604  public:
 605   CLDCallback() {}
 606   void do_cld(ClassLoaderData* cld) {
 607     assert(cld != NULL, "invariant");
 608     if (cld->has_class_mirror_holder()) {
 609       return;
 610     }
 611     do_class_loader_data(cld);
 612   }
 613 };
 614 
 615 static void do_class_loaders() {
 616   CLDCallback cld_cb;
 617   ClassLoaderDataGraph::loaded_cld_do(&cld_cb);
 618 }
 619 
 620 typedef SerializePredicate<CldPtr> CldPredicate;
 621 typedef JfrPredicatedTypeWriterImplHost<CldPtr, CldPredicate, write__classloader> CldWriterImpl;
 622 typedef JfrTypeWriterHost<CldWriterImpl, TYPE_CLASSLOADER> CldWriter;
 623 typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
 624 typedef JfrArtifactCallbackHost<CldPtr, CldWriterWithClear> CldCallback;
 625 typedef KlassToFieldEnvelope<KlassCldFieldSelector, CldWriter> KlassCldWriter;
 626 typedef KlassToFieldEnvelope<ModuleCldFieldSelector, CldWriter> ModuleCldWriter;
 627 typedef CompositeFunctor<KlassPtr, KlassCldWriter, ModuleCldWriter> KlassAndModuleCldWriter;
 628 
 629 typedef LeakPredicate<CldPtr> LeakCldPredicate;
 630 typedef JfrPredicatedTypeWriterImplHost<CldPtr, LeakCldPredicate, write__classloader__leakp> LeakCldWriterImpl;
 631 typedef JfrTypeWriterHost<LeakCldWriterImpl, TYPE_CLASSLOADER> LeakCldWriter;
 632 
 633 typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
 634 typedef KlassToFieldEnvelope<KlassCldFieldSelector, CompositeCldWriter> KlassCompositeCldWriter;
 635 typedef KlassToFieldEnvelope<ModuleCldFieldSelector, CompositeCldWriter> ModuleCompositeCldWriter;
 636 typedef CompositeFunctor<KlassPtr, KlassCompositeCldWriter, ModuleCompositeCldWriter> KlassAndModuleCompositeCldWriter;
 637 typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
 638 typedef JfrArtifactCallbackHost<CldPtr, CompositeCldWriterWithClear> CompositeCldCallback;
 639 
 640 static void write_classloaders() {
 641   assert(_writer != NULL, "invariant");
 642   CldWriter cldw(_writer, _class_unload);
 643   KlassCldWriter kcw(&cldw);
 644   ModuleCldWriter mcw(&cldw);
 645   KlassAndModuleCldWriter kmcw(&kcw, &mcw);
 646   if (current_epoch()) {
 647     _artifacts->iterate_klasses(kmcw);
 648     _artifacts->tally(cldw);
 649     return;
 650   }
 651   assert(previous_epoch(), "invariant");
 652   if (_leakp_writer == NULL) {
 653     _artifacts->iterate_klasses(kmcw);
 654     ClearArtifact<CldPtr> clear;
 655     CldWriterWithClear cldwwc(&cldw, &clear);
 656     CldCallback callback(&cldwwc);
 657     _subsystem_callback = &callback;
 658     do_class_loaders();
 659   } else {
 660     LeakCldWriter lcldw(_leakp_writer, _class_unload);
 661     CompositeCldWriter ccldw(&lcldw, &cldw);
 662     KlassCompositeCldWriter kccldw(&ccldw);
 663     ModuleCompositeCldWriter mccldw(&ccldw);
 664     KlassAndModuleCompositeCldWriter kmccldw(&kccldw, &mccldw);
 665     _artifacts->iterate_klasses(kmccldw);
 666     ClearArtifact<CldPtr> clear;
 667     CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
 668     CompositeCldCallback callback(&ccldwwc);
 669     _subsystem_callback = &callback;
 670     do_class_loaders();
 671   }
 672   _artifacts->tally(cldw);
 673 }
 674 
 675 typedef JfrArtifactCallbackHost<CldPtr, ClearArtifact<CldPtr> > ClearCLDCallback;
 676 
 677 static void clear_classloaders() {
 678   ClearArtifact<CldPtr> clear;
 679   ClearCLDCallback callback(&clear);
 680   _subsystem_callback = &callback;
 681   do_class_loaders();
 682 }
 683 
 684 static u1 get_visibility(MethodPtr method) {
 685   assert(method != NULL, "invariant");
 686   return const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0;
 687 }
 688 
 689 template <>
 690 void set_serialized<Method>(MethodPtr method) {
 691   assert(method != NULL, "invariant");
 692   SET_METHOD_SERIALIZED(method);
 693   assert(IS_METHOD_SERIALIZED(method), "invariant");
 694   CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(method);
 695 }
 696 
 697 static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leakp) {
 698   assert(writer != NULL, "invariant");
 699   assert(method != NULL, "invariant");
 700   assert(_artifacts != NULL, "invariant");
 701   KlassPtr klass = method->method_holder();
 702   assert(klass != NULL, "invariant");
 703   writer->write(method_id(klass, method));
 704   writer->write(artifact_id(klass));
 705   writer->write(mark_symbol(method->name(), leakp));
 706   writer->write(mark_symbol(method->signature(), leakp));
 707   writer->write((u2)get_flags(method));
 708   writer->write(get_visibility(method));
 709   return 1;
 710 }
 711 
 712 int write__method(JfrCheckpointWriter* writer, const void* m) {
 713   assert(m != NULL, "invariant");
 714   MethodPtr method = (MethodPtr)m;
 715   set_serialized(method);
 716   return write_method(writer, method, false);
 717 }
 718 
 719 int write__method__leakp(JfrCheckpointWriter* writer, const void* m) {
 720   assert(m != NULL, "invariant");
 721   MethodPtr method = (MethodPtr)m;
 722   return write_method(writer, method, true);
 723 }
 724 
 725 class BitMapFilter {
 726   ResourceBitMap _bitmap;
 727  public:
 728   explicit BitMapFilter(int length = 0) : _bitmap((size_t)length) {}
 729   bool operator()(size_t idx) {
 730     if (_bitmap.size() == 0) {
 731       return true;
 732     }
 733     if (_bitmap.at(idx)) {
 734       return false;
 735     }
 736     _bitmap.set_bit(idx);
 737     return true;
 738   }
 739 };
 740 
 741 class AlwaysTrue {
 742  public:
 743   explicit AlwaysTrue(int length = 0) {}
 744   bool operator()(size_t idx) {
 745     return true;
 746   }
 747 };
 748 
 749 template <typename MethodCallback, typename KlassCallback, class Filter, bool leakp>
 750 class MethodIteratorHost {
 751  private:
 752   MethodCallback _method_cb;
 753   KlassCallback _klass_cb;
 754   MethodUsedPredicate<leakp> _method_used_predicate;
 755   MethodFlagPredicate<leakp> _method_flag_predicate;
 756  public:
 757   MethodIteratorHost(JfrCheckpointWriter* writer,
 758                      bool current_epoch = false,
 759                      bool class_unload = false,
 760                      bool skip_header = false) :
 761     _method_cb(writer, class_unload, skip_header),
 762     _klass_cb(writer, class_unload, skip_header),
 763     _method_used_predicate(current_epoch),
 764     _method_flag_predicate(current_epoch) {}
 765 
 766   bool operator()(KlassPtr klass) {
 767     if (_method_used_predicate(klass)) {
 768       const InstanceKlass* ik = InstanceKlass::cast(klass);
 769       const int len = ik->methods()->length();
 770       Filter filter(ik->previous_versions() != NULL ? len : 0);
 771       while (ik != NULL) {
 772         for (int i = 0; i < len; ++i) {
 773           MethodPtr method = ik->methods()->at(i);
 774           if (_method_flag_predicate(method) && filter(i)) {
 775             _method_cb(method);
 776           }
 777         }
 778         // There can be multiple versions of the same method running
 779         // due to redefinition. Need to inspect the complete set of methods.
 780         ik = ik->previous_versions();
 781       }
 782     }
 783     return _klass_cb(klass);
 784   }
 785 
 786   int count() const { return _method_cb.count(); }
 787   void add(int count) { _method_cb.add(count); }
 788 };
 789 
 790 template <typename T, template <typename> class Impl>
 791 class Wrapper {
 792   Impl<T> _t;
 793  public:
 794   Wrapper(JfrCheckpointWriter*, bool, bool) : _t() {}
 795   bool operator()(T const& value) {
 796     return _t(value);
 797   }
 798 };
 799 
 800 template <typename T>
 801 class EmptyStub {
 802  public:
 803   bool operator()(T const& value) { return true; }
 804 };
 805 
 806 typedef SerializePredicate<MethodPtr> MethodPredicate;
 807 typedef JfrPredicatedTypeWriterImplHost<MethodPtr, MethodPredicate, write__method> MethodWriterImplTarget;
 808 typedef Wrapper<KlassPtr, EmptyStub> KlassCallbackStub;
 809 typedef JfrTypeWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
 810 typedef MethodIteratorHost<MethodWriterImpl, KlassCallbackStub, BitMapFilter, false> MethodWriter;
 811 
 812 typedef LeakPredicate<MethodPtr> LeakMethodPredicate;
 813 typedef JfrPredicatedTypeWriterImplHost<MethodPtr, LeakMethodPredicate, write__method__leakp> LeakMethodWriterImplTarget;
 814 typedef JfrTypeWriterHost<LeakMethodWriterImplTarget, TYPE_METHOD> LeakMethodWriterImpl;
 815 typedef MethodIteratorHost<LeakMethodWriterImpl, KlassCallbackStub, BitMapFilter, true> LeakMethodWriter;
 816 typedef MethodIteratorHost<LeakMethodWriterImpl, KlassCallbackStub, BitMapFilter, true> LeakMethodWriter;
 817 typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
 818 
 819 static void write_methods() {
 820   assert(_writer != NULL, "invariant");
 821   MethodWriter mw(_writer, current_epoch(), _class_unload);
 822   if (_leakp_writer == NULL) {
 823     _artifacts->iterate_klasses(mw);
 824   } else {
 825     LeakMethodWriter lpmw(_leakp_writer, current_epoch(), _class_unload);
 826     CompositeMethodWriter cmw(&lpmw, &mw);
 827     _artifacts->iterate_klasses(cmw);
 828   }
 829   _artifacts->tally(mw);
 830 }
 831 
 832 template <>
 833 void set_serialized<JfrSymbolId::SymbolEntry>(SymbolEntryPtr ptr) {
 834   assert(ptr != NULL, "invariant");
 835   ptr->set_serialized();
 836   assert(ptr->is_serialized(), "invariant");
 837 }
 838 
 839 template <>
 840 void set_serialized<JfrSymbolId::CStringEntry>(CStringEntryPtr ptr) {
 841   assert(ptr != NULL, "invariant");
 842   ptr->set_serialized();
 843   assert(ptr->is_serialized(), "invariant");
 844 }
 845 
 846 static int write_symbol(JfrCheckpointWriter* writer, SymbolEntryPtr entry, bool leakp) {
 847   assert(writer != NULL, "invariant");
 848   assert(entry != NULL, "invariant");
 849   ResourceMark rm;
 850   writer->write(create_symbol_id(entry->id()));
 851   writer->write(entry->value()->as_C_string());
 852   return 1;
 853 }
 854 
 855 int write__symbol(JfrCheckpointWriter* writer, const void* e) {
 856   assert(e != NULL, "invariant");
 857   SymbolEntryPtr entry = (SymbolEntryPtr)e;
 858   set_serialized(entry);
 859   return write_symbol(writer, entry, false);
 860 }
 861 
 862 int write__symbol__leakp(JfrCheckpointWriter* writer, const void* e) {
 863   assert(e != NULL, "invariant");
 864   SymbolEntryPtr entry = (SymbolEntryPtr)e;
 865   return write_symbol(writer, entry, true);
 866 }
 867 
 868 static int write_cstring(JfrCheckpointWriter* writer, CStringEntryPtr entry, bool leakp) {
 869   assert(writer != NULL, "invariant");
 870   assert(entry != NULL, "invariant");
 871   writer->write(create_symbol_id(entry->id()));
 872   writer->write(entry->value());
 873   return 1;
 874 }
 875 
 876 int write__cstring(JfrCheckpointWriter* writer, const void* e) {
 877   assert(e != NULL, "invariant");
 878   CStringEntryPtr entry = (CStringEntryPtr)e;
 879   set_serialized(entry);
 880   return write_cstring(writer, entry, false);
 881 }
 882 
 883 int write__cstring__leakp(JfrCheckpointWriter* writer, const void* e) {
 884   assert(e != NULL, "invariant");
 885   CStringEntryPtr entry = (CStringEntryPtr)e;
 886   return write_cstring(writer, entry, true);
 887 }
 888 
 889 typedef SymbolPredicate<SymbolEntryPtr, false> SymPredicate;
 890 typedef JfrPredicatedTypeWriterImplHost<SymbolEntryPtr, SymPredicate, write__symbol> SymbolEntryWriterImpl;
 891 typedef JfrTypeWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
 892 typedef SymbolPredicate<CStringEntryPtr, false> CStringPredicate;
 893 typedef JfrPredicatedTypeWriterImplHost<CStringEntryPtr, CStringPredicate, write__cstring> CStringEntryWriterImpl;
 894 typedef JfrTypeWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
 895 
 896 typedef SymbolPredicate<SymbolEntryPtr, true> LeakSymPredicate;
 897 typedef JfrPredicatedTypeWriterImplHost<SymbolEntryPtr, LeakSymPredicate, write__symbol__leakp> LeakSymbolEntryWriterImpl;
 898 typedef JfrTypeWriterHost<LeakSymbolEntryWriterImpl, TYPE_SYMBOL> LeakSymbolEntryWriter;
 899 typedef CompositeFunctor<SymbolEntryPtr, LeakSymbolEntryWriter, SymbolEntryWriter> CompositeSymbolWriter;
 900 typedef SymbolPredicate<CStringEntryPtr, true> LeakCStringPredicate;
 901 typedef JfrPredicatedTypeWriterImplHost<CStringEntryPtr, LeakCStringPredicate, write__cstring__leakp> LeakCStringEntryWriterImpl;
 902 typedef JfrTypeWriterHost<LeakCStringEntryWriterImpl, TYPE_SYMBOL> LeakCStringEntryWriter;
 903 typedef CompositeFunctor<CStringEntryPtr, LeakCStringEntryWriter, CStringEntryWriter> CompositeCStringWriter;
 904 
 905 static void write_symbols_with_leakp() {
 906   assert(_leakp_writer != NULL, "invariant");
 907   SymbolEntryWriter sw(_writer, _class_unload);
 908   LeakSymbolEntryWriter lsw(_leakp_writer, _class_unload);
 909   CompositeSymbolWriter csw(&lsw, &sw);
 910   _artifacts->iterate_symbols(csw);
 911   CStringEntryWriter ccsw(_writer, _class_unload, true); // skip header
 912   LeakCStringEntryWriter lccsw(_leakp_writer, _class_unload, true); // skip header
 913   CompositeCStringWriter cccsw(&lccsw, &ccsw);
 914   _artifacts->iterate_cstrings(cccsw);
 915   sw.add(ccsw.count());
 916   lsw.add(lccsw.count());
 917   _artifacts->tally(sw);
 918 }
 919 
 920 static void write_symbols() {
 921   assert(_writer != NULL, "invariant");
 922   if (_leakp_writer != NULL) {
 923     write_symbols_with_leakp();
 924     return;
 925   }
 926   SymbolEntryWriter sw(_writer, _class_unload);
 927   _artifacts->iterate_symbols(sw);
 928   CStringEntryWriter csw(_writer, _class_unload, true); // skip header
 929   _artifacts->iterate_cstrings(csw);
 930   sw.add(csw.count());
 931   _artifacts->tally(sw);
 932 }
 933 
 934 typedef Wrapper<KlassPtr, ClearArtifact> ClearKlassBits;
 935 typedef Wrapper<MethodPtr, ClearArtifact> ClearMethodFlag;
 936 typedef MethodIteratorHost<ClearMethodFlag, ClearKlassBits, AlwaysTrue, false> ClearKlassAndMethods;
 937 
 938 static bool clear_artifacts = false;
 939 
 940 static void clear_klasses_and_methods() {
 941   ClearKlassAndMethods clear(_writer);
 942   _artifacts->iterate_klasses(clear);
 943 }
 944 
 945 static size_t teardown() {
 946   assert(_artifacts != NULL, "invariant");
 947   const size_t total_count = _artifacts->total_count();
 948   if (previous_epoch()) {
 949     clear_klasses_and_methods();
 950     clear_artifacts = true;
 951     ++checkpoint_id;
 952   }
 953   return total_count;
 954 }
 955 
 956 static void setup(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload, bool flushpoint) {
 957   _writer = writer;
 958   _leakp_writer = leakp_writer;
 959   _class_unload = class_unload;
 960   _flushpoint = flushpoint;
 961   if (_artifacts == NULL) {
 962     _artifacts = new JfrArtifactSet(class_unload);
 963   } else {
 964     _artifacts->initialize(class_unload, clear_artifacts);
 965   }
 966   clear_artifacts = false;
 967   assert(_artifacts != NULL, "invariant");
 968   assert(!_artifacts->has_klass_entries(), "invariant");
 969 }
 970 
 971 /**
 972  * Write all "tagged" (in-use) constant artifacts and their dependencies.
 973  */
 974 size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload, bool flushpoint) {
 975   assert(writer != NULL, "invariant");
 976   ResourceMark rm;
 977   setup(writer, leakp_writer, class_unload, flushpoint);
 978   // write order is important because an individual write step
 979   // might tag an artifact to be written in a subsequent step
 980   if (!write_klasses()) {
 981     return 0;
 982   }
 983   write_packages();
 984   write_modules();
 985   write_classloaders();
 986   write_methods();
 987   write_symbols();
 988   return teardown();
 989 }
 990 
 991 /**
 992  * Clear all tags from the previous epoch.
 993  */
 994 void JfrTypeSet::clear() {
 995   clear_artifacts = true;
 996   setup(NULL, NULL, false, false);
 997   register_klasses();
 998   clear_packages();
 999   clear_modules();
1000   clear_classloaders();
1001   clear_klasses_and_methods();
1002 }
--- EOF ---