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