src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.cpp

Mon, 12 Aug 2019 18:30:40 +0300

author
apetushkov
date
Mon, 12 Aug 2019 18:30:40 +0300
changeset 9858
b985cbb00e68
child 9926
d20a5f399218
child 9941
45c8de52649c
permissions
-rw-r--r--

8223147: JFR Backport
8199712: Flight Recorder
8203346: JFR: Inconsistent signature of jfr_add_string_constant
8195817: JFR.stop should require name of recording
8195818: JFR.start should increase autogenerated name by one
8195819: Remove recording=x from jcmd JFR.check output
8203921: JFR thread sampling is missing fixes from JDK-8194552
8203929: Limit amount of data for JFR.dump
8203664: JFR start failure after AppCDS archive created with JFR StartFlightRecording
8003209: JFR events for network utilization
8207392: [PPC64] Implement JFR profiling
8202835: jfr/event/os/TestSystemProcess.java fails on missing events
Summary: Backport JFR from JDK11. Initial integration
Reviewed-by: neugens

     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  */
    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"
    49 // incremented on each checkpoint
    50 static u8 checkpoint_id = 0;
    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)))
    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;
    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 // }
    71 static traceid cld_id(CldPtr cld) {
    72   assert(cld != NULL, "invariant");
    73   return cld->is_anonymous() ? 0 : TRACE_ID(cld);
    74 }
    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 }
    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 };
   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  */
   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 }
   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;
   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 }
   169 typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget;
   170 typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
   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 // }
   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;
   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 }
   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;
   226 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
   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 }
   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 }
   243 typedef JfrArtifactWriterImplHost<SymbolEntryPtr, write__artifact__symbol__entry> SymbolEntryWriterImpl;
   244 typedef JfrArtifactWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
   246 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
   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 }
   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 }
   261 typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__cstring__entry> CStringEntryWriterImpl;
   262 typedef JfrArtifactWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
   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   }
   276   SymbolEntryPtr entry = artifacts->map_symbol(JfrSymbolId::regular_klass_name_hash_code(ik));
   277   return write__artifact__symbol__entry__(writer, entry);
   278 }
   280 int _compare_traceid_(const traceid& lhs, const traceid& rhs) {
   281   return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
   282 }
   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;
   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);
   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) {}
   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 };
   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 }
   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 // }
   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 // }
   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 }
   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 }
   451 typedef KlassSymbolWriterImpl<LeakPredicate> LeakKlassSymbolWriterImpl;
   452 typedef JfrArtifactWriterHost<LeakKlassSymbolWriterImpl, TYPE_SYMBOL> LeakKlassSymbolWriter;
   454 class ClearKlassAndMethods {
   455  private:
   456   ClearArtifact<KlassPtr> _clear_klass_tag_bits;
   457   ClearArtifact<MethodPtr> _clear_method_flag;
   458   MethodUsedPredicate<false> _method_used_predicate;
   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 };
   478 typedef CompositeFunctor<KlassPtr,
   479                          TagLeakpKlassArtifact,
   480                          LeakKlassWriter> LeakpKlassArtifactTagging;
   482 typedef CompositeFunctor<KlassPtr,
   483                          LeakpKlassArtifactTagging,
   484                          KlassWriter> CompositeKlassWriter;
   486 typedef CompositeFunctor<KlassPtr,
   487                          CompositeKlassWriter,
   488                          KlassArtifactRegistrator> CompositeKlassWriterRegistration;
   490 typedef CompositeFunctor<KlassPtr,
   491                          KlassWriter,
   492                          KlassArtifactRegistrator> KlassWriterRegistration;
   494 typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
   495 typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
   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 }
   528 // XXX
   529 // typedef CompositeFunctor<PkgPtr,
   530 //                          PackageWriter,
   531 //                          ClearArtifact<PkgPtr> > PackageWriterWithClear;
   533 // typedef CompositeFunctor<PkgPtr,
   534 //                          LeakPackageWriter,
   535 //                          PackageWriter> CompositePackageWriter;
   537 // typedef CompositeFunctor<PkgPtr,
   538 //                          CompositePackageWriter,
   539 //                          ClearArtifact<PkgPtr> > CompositePackageWriterWithClear;
   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 // };
   550 // typedef KlassToFieldEnvelope<PackageFieldSelector,
   551 //                              PackageWriterWithClear> KlassPackageWriterWithClear;
   553 // typedef KlassToFieldEnvelope<PackageFieldSelector,
   554 //                              CompositePackageWriterWithClear> KlassCompositePackageWriterWithClear;
   556 // typedef JfrArtifactCallbackHost<PkgPtr, PackageWriterWithClear> PackageCallback;
   557 // typedef JfrArtifactCallbackHost<PkgPtr, CompositePackageWriterWithClear> CompositePackageCallback;
   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 // }
   590 // typedef CompositeFunctor<ModPtr,
   591 //                          ModuleWriter,
   592 //                          ClearArtifact<ModPtr> > ModuleWriterWithClear;
   594 // typedef CompositeFunctor<ModPtr,
   595 //                          LeakModuleWriter,
   596 //                          ModuleWriter> CompositeModuleWriter;
   598 // typedef CompositeFunctor<ModPtr,
   599 //                          CompositeModuleWriter,
   600 //                          ClearArtifact<ModPtr> > CompositeModuleWriterWithClear;
   602 // typedef JfrArtifactCallbackHost<ModPtr, ModuleWriterWithClear> ModuleCallback;
   603 // typedef JfrArtifactCallbackHost<ModPtr, CompositeModuleWriterWithClear> CompositeModuleCallback;
   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 // };
   616 // typedef KlassToFieldEnvelope<ModuleFieldSelector,
   617 //                              ModuleWriterWithClear> KlassModuleWriterWithClear;
   619 // typedef KlassToFieldEnvelope<ModuleFieldSelector,
   620 //                              CompositeModuleWriterWithClear> KlassCompositeModuleWriterWithClear;
   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;
   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 };
   638 typedef KlassToFieldEnvelope<CldFieldSelector, CldWriterWithClear> KlassCldWriterWithClear;
   639 typedef KlassToFieldEnvelope<CldFieldSelector, CompositeCldWriterWithClear> KlassCompositeCldWriterWithClear;
   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 }
   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;
   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) {}
   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   }
   702   int count() const { return _method_functor.count(); }
   703   void add(int count) { _method_functor.add(count); }
   704 };
   706 typedef MethodIteratorHost<true /*leakp */,  MethodWriterImpl> LeakMethodWriter;
   707 typedef MethodIteratorHost<false, MethodWriterImpl> MethodWriter;
   708 typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
   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 }
   747 bool JfrTypeSet::_class_unload = false;
   748 JfrArtifactSet* JfrTypeSet::_artifacts = NULL;
   749 JfrArtifactClosure* JfrTypeSet::_subsystem_callback = NULL;
   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 }
   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 }
   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 }
   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 }
   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 // }
   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 // }
   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 // }
   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 }
   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 }
   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 };
   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 }
   859 static void clear_artifacts(JfrArtifactSet* artifacts,
   860                             bool class_unload) {
   861   assert(artifacts != NULL, "invariant");
   862   assert(artifacts->has_klass_entries(), "invariant");
   864   // untag
   865   ClearKlassAndMethods clear(class_unload);
   866   artifacts->iterate_klasses(clear);
   867   artifacts->clear();
   868 }
   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
   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 }

mercurial