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

Mon, 15 Jun 2020 14:08:11 +0300

author
apetushkov
date
Mon, 15 Jun 2020 14:08:11 +0300
changeset 9926
d20a5f399218
parent 9858
b985cbb00e68
child 9949
fb74ae591209
permissions
-rw-r--r--

8245167: Top package in method profiling shows null in JMC
Reviewed-by: neugens
Contributed-by: asemenov@azul.com

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

mercurial