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

Tue, 02 Jun 2020 14:29:43 +0800

author
ddong
date
Tue, 02 Jun 2020 14:29:43 +0800
changeset 9941
45c8de52649c
parent 9858
b985cbb00e68
child 9949
fb74ae591209
permissions
-rw-r--r--

8246310: Clean commented-out code about ModuleEntry andPackageEntry in JFR
Reviewed-by: adinn

     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 #include "classfile/symbolTable.hpp"
    29 #include "classfile/systemDictionary.hpp"
    30 #include "jfr/jfr.hpp"
    31 #include "jfr/jni/jfrGetAllEventClasses.hpp"
    32 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
    33 #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
    34 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
    35 #include "jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp"
    36 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
    37 #include "jfr/recorder/storage/jfrBuffer.hpp"
    38 #include "jfr/utilities/jfrHashtable.hpp"
    39 #include "jfr/utilities/jfrTypes.hpp"
    40 #include "memory/iterator.hpp"
    41 #include "memory/resourceArea.hpp"
    42 #include "oops/instanceKlass.hpp"
    43 #include "oops/objArrayKlass.hpp"
    44 #include "oops/oop.inline.hpp"
    45 #include "memory/resourceArea.hpp"
    46 #include "utilities/accessFlags.hpp"
    48 // incremented on each checkpoint
    49 static u8 checkpoint_id = 0;
    51 // creates a unique id by combining a checkpoint relative symbol id (2^24)
    52 // with the current checkpoint id (2^40)
    53 #define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))
    55 typedef const Klass* KlassPtr;
    56 typedef const ClassLoaderData* CldPtr;
    57 typedef const Method* MethodPtr;
    58 typedef const Symbol* SymbolPtr;
    59 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
    60 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
    62 static traceid cld_id(CldPtr cld) {
    63   assert(cld != NULL, "invariant");
    64   return cld->is_anonymous() ? 0 : TRACE_ID(cld);
    65 }
    67 static void tag_leakp_klass_artifacts(KlassPtr k, bool class_unload) {
    68   assert(k != NULL, "invariant");
    69   CldPtr cld = k->class_loader_data();
    70   assert(cld != NULL, "invariant");
    71   if (!cld->is_anonymous()) {
    72     tag_leakp_artifact(cld, class_unload);
    73   }
    74 }
    76 class TagLeakpKlassArtifact {
    77   bool _class_unload;
    78  public:
    79   TagLeakpKlassArtifact(bool class_unload) : _class_unload(class_unload) {}
    80   bool operator()(KlassPtr klass) {
    81     if (_class_unload) {
    82       if (LEAKP_USED_THIS_EPOCH(klass)) {
    83         tag_leakp_klass_artifacts(klass, _class_unload);
    84       }
    85     } else {
    86       if (LEAKP_USED_PREV_EPOCH(klass)) {
    87         tag_leakp_klass_artifacts(klass, _class_unload);
    88       }
    89     }
    90     return true;
    91   }
    92 };
    94 /*
    95  * In C++03, functions used as template parameters must have external linkage;
    96  * this restriction was removed in C++11. Change back to "static" and
    97  * rename functions when C++11 becomes available.
    98  *
    99  * The weird naming is an effort to decrease the risk of name clashes.
   100  */
   102 int write__artifact__klass(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
   103   assert(writer != NULL, "invariant");
   104   assert(artifacts != NULL, "invariant");
   105   assert(k != NULL, "invariant");
   106   KlassPtr klass = (KlassPtr)k;
   107   traceid pkg_id = 0;
   108   KlassPtr theklass = klass;
   109   if (theklass->oop_is_objArray()) {
   110     const ObjArrayKlass* obj_arr_klass = ObjArrayKlass::cast((Klass*)klass);
   111     theklass = obj_arr_klass->bottom_klass();
   112   }
   113   if (theklass->oop_is_instance()) {
   114     pkg_id = 0;
   115   } else {
   116     assert(theklass->oop_is_typeArray(), "invariant");
   117   }
   118   const traceid symbol_id = artifacts->mark(klass);
   119   assert(symbol_id > 0, "need to have an address for symbol!");
   120   writer->write(TRACE_ID(klass));
   121   writer->write(cld_id(klass->class_loader_data()));
   122   writer->write((traceid)CREATE_SYMBOL_ID(symbol_id));
   123   writer->write(pkg_id);
   124   writer->write((s4)klass->access_flags().get_flags());
   125   return 1;
   126 }
   128 typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
   129 typedef JfrPredicatedArtifactWriterImplHost<KlassPtr, LeakKlassPredicate, write__artifact__klass> LeakKlassWriterImpl;
   130 typedef JfrArtifactWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
   131 typedef JfrArtifactWriterImplHost<KlassPtr, write__artifact__klass> KlassWriterImpl;
   132 typedef JfrArtifactWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
   134 int write__artifact__method(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
   135   assert(writer != NULL, "invariant");
   136   assert(artifacts != NULL, "invariant");
   137   assert(m != NULL, "invariant");
   138   MethodPtr method = (MethodPtr)m;
   139   const traceid method_name_symbol_id = artifacts->mark(method->name());
   140   assert(method_name_symbol_id > 0, "invariant");
   141   const traceid method_sig_symbol_id = artifacts->mark(method->signature());
   142   assert(method_sig_symbol_id > 0, "invariant");
   143   KlassPtr klass = method->method_holder();
   144   assert(klass != NULL, "invariant");
   145   assert(METHOD_USED_ANY_EPOCH(klass), "invariant");
   146   writer->write((u8)METHOD_ID(klass, method));
   147   writer->write((u8)TRACE_ID(klass));
   148   writer->write((u8)CREATE_SYMBOL_ID(method_name_symbol_id));
   149   writer->write((u8)CREATE_SYMBOL_ID(method_sig_symbol_id));
   150   writer->write((u2)method->access_flags().get_flags());
   151   writer->write(const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0);
   152   return 1;
   153 }
   155 typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget;
   156 typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
   158 int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) {
   159   assert(c != NULL, "invariant");
   160   CldPtr cld = (CldPtr)c;
   161   assert(!cld->is_anonymous(), "invariant");
   162   const traceid cld_id = TRACE_ID(cld);
   163   // class loader type
   164   const Klass* class_loader_klass = cld->class_loader() != NULL ? cld->class_loader()->klass() : NULL;
   165   if (class_loader_klass == NULL) {
   166     // (primordial) boot class loader
   167     writer->write(cld_id); // class loader instance id
   168     writer->write((traceid)0);  // class loader type id (absence of)
   169     writer->write((traceid)CREATE_SYMBOL_ID(1)); // 1 maps to synthetic name -> "bootstrap"
   170   } else {
   171     Symbol* symbol_name = class_loader_klass->name();
   172     const traceid symbol_name_id = symbol_name != NULL ? artifacts->mark(symbol_name) : 0;
   173     writer->write(cld_id); // class loader instance id
   174     writer->write(TRACE_ID(class_loader_klass)); // class loader type id
   175     writer->write(symbol_name_id == 0 ? (traceid)0 :
   176       (traceid)CREATE_SYMBOL_ID(symbol_name_id)); // class loader instance name
   177   }
   178   return 1;
   179 }
   181 typedef LeakPredicate<CldPtr> LeakCldPredicate;
   182 int _compare_cld_ptr_(CldPtr const& lhs, CldPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
   183 typedef UniquePredicate<CldPtr, _compare_cld_ptr_> CldPredicate;
   184 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, LeakCldPredicate, write__artifact__classloader> LeakCldWriterImpl;
   185 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, CldPredicate, write__artifact__classloader> CldWriterImpl;
   186 typedef JfrArtifactWriterHost<LeakCldWriterImpl, TYPE_CLASSLOADER> LeakCldWriter;
   187 typedef JfrArtifactWriterHost<CldWriterImpl, TYPE_CLASSLOADER> CldWriter;
   189 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
   191 static int write__artifact__symbol__entry__(JfrCheckpointWriter* writer,
   192                                             SymbolEntryPtr entry) {
   193   assert(writer != NULL, "invariant");
   194   assert(entry != NULL, "invariant");
   195   ResourceMark rm;
   196   writer->write(CREATE_SYMBOL_ID(entry->id()));
   197   writer->write(entry->value()->as_C_string());
   198   return 1;
   199 }
   201 int write__artifact__symbol__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
   202   assert(e != NULL, "invariant");
   203   return write__artifact__symbol__entry__(writer, (SymbolEntryPtr)e);
   204 }
   206 typedef JfrArtifactWriterImplHost<SymbolEntryPtr, write__artifact__symbol__entry> SymbolEntryWriterImpl;
   207 typedef JfrArtifactWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
   209 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
   211 static int write__artifact__cstring__entry__(JfrCheckpointWriter* writer, CStringEntryPtr entry) {
   212   assert(writer != NULL, "invariant");
   213   assert(entry != NULL, "invariant");
   214   writer->write(CREATE_SYMBOL_ID(entry->id()));
   215   writer->write(entry->value());
   216   return 1;
   217 }
   219 int write__artifact__cstring__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
   220   assert(e != NULL, "invariant");
   221   return write__artifact__cstring__entry__(writer, (CStringEntryPtr)e);
   222 }
   224 typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__cstring__entry> CStringEntryWriterImpl;
   225 typedef JfrArtifactWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
   227 int write__artifact__klass__symbol(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
   228   assert(writer != NULL, "invariant");
   229   assert(artifacts != NULL, "invaiant");
   230   assert(k != NULL, "invariant");
   231   const InstanceKlass* const ik = (const InstanceKlass*)k;
   232   if (ik->is_anonymous()) {
   233     CStringEntryPtr entry =
   234       artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
   235     assert(entry != NULL, "invariant");
   236     return write__artifact__cstring__entry__(writer, entry);
   237   }
   239   SymbolEntryPtr entry = artifacts->map_symbol(JfrSymbolId::regular_klass_name_hash_code(ik));
   240   return write__artifact__symbol__entry__(writer, entry);
   241 }
   243 int _compare_traceid_(const traceid& lhs, const traceid& rhs) {
   244   return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
   245 }
   247 template <template <typename> class Predicate>
   248 class KlassSymbolWriterImpl {
   249  private:
   250   JfrCheckpointWriter* _writer;
   251   JfrArtifactSet* _artifacts;
   252   Predicate<KlassPtr> _predicate;
   253   MethodUsedPredicate<true> _method_used_predicate;
   254   MethodFlagPredicate _method_flag_predicate;
   255   UniquePredicate<traceid, _compare_traceid_> _unique_predicate;
   257   int klass_symbols(KlassPtr klass);
   258   int class_loader_symbols(CldPtr cld);
   259   int method_symbols(KlassPtr klass);
   261  public:
   262   typedef KlassPtr Type;
   263   KlassSymbolWriterImpl(JfrCheckpointWriter* writer,
   264                         JfrArtifactSet* artifacts,
   265                         bool class_unload) : _writer(writer),
   266                                              _artifacts(artifacts),
   267                                              _predicate(class_unload),
   268                                              _method_used_predicate(class_unload),
   269                                              _method_flag_predicate(class_unload),
   270                                              _unique_predicate(class_unload) {}
   272   int operator()(KlassPtr klass) {
   273     assert(klass != NULL, "invariant");
   274     int count = 0;
   275     if (_predicate(klass)) {
   276       count += klass_symbols(klass);
   277       CldPtr cld = klass->class_loader_data();
   278       assert(cld != NULL, "invariant");
   279       if (!cld->is_anonymous()) {
   280         count += class_loader_symbols(cld);
   281       }
   282       if (_method_used_predicate(klass)) {
   283         count += method_symbols(klass);
   284       }
   285     }
   286     return count;
   287   }
   288 };
   290 template <template <typename> class Predicate>
   291 int KlassSymbolWriterImpl<Predicate>::klass_symbols(KlassPtr klass) {
   292   assert(klass != NULL, "invariant");
   293   assert(_predicate(klass), "invariant");
   294   const InstanceKlass* const ik = (const InstanceKlass*)klass;
   295   if (ik->is_anonymous()) {
   296     CStringEntryPtr entry =
   297       this->_artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
   298     assert(entry != NULL, "invariant");
   299     return _unique_predicate(entry->id()) ? write__artifact__cstring__entry__(this->_writer, entry) : 0;
   300   }
   301   SymbolEntryPtr entry = this->_artifacts->map_symbol(ik->name());
   302   assert(entry != NULL, "invariant");
   303   return _unique_predicate(entry->id()) ? write__artifact__symbol__entry__(this->_writer, entry) : 0;
   304 }
   306 template <template <typename> class Predicate>
   307 int KlassSymbolWriterImpl<Predicate>::class_loader_symbols(CldPtr cld) {
   308   assert(cld != NULL, "invariant");
   309   assert(!cld->is_anonymous(), "invariant");
   310   int count = 0;
   311   // class loader type
   312   const Klass* class_loader_klass = cld->class_loader() != NULL ? cld->class_loader()->klass() : NULL;
   313   if (class_loader_klass == NULL) {
   314     // (primordial) boot class loader
   315     CStringEntryPtr entry = this->_artifacts->map_cstring(0);
   316     assert(entry != NULL, "invariant");
   317     assert(strncmp(entry->literal(),
   318       BOOTSTRAP_LOADER_NAME,
   319       BOOTSTRAP_LOADER_NAME_LEN) == 0, "invariant");
   320     if (_unique_predicate(entry->id())) {
   321       count += write__artifact__cstring__entry__(this->_writer, entry);
   322     }
   323   } else {
   324     const Symbol* class_loader_name = class_loader_klass->name()/* XXX TODO cld->name()*/;
   325     if (class_loader_name != NULL) {
   326       SymbolEntryPtr entry = this->_artifacts->map_symbol(class_loader_name);
   327       assert(entry != NULL, "invariant");
   328       if (_unique_predicate(entry->id())) {
   329         count += write__artifact__symbol__entry__(this->_writer, entry);
   330       }
   331     }
   332   }
   333   return count;
   334 }
   336 template <template <typename> class Predicate>
   337 int KlassSymbolWriterImpl<Predicate>::method_symbols(KlassPtr klass) {
   338   assert(_predicate(klass), "invariant");
   339   assert(_method_used_predicate(klass), "invariant");
   340   assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
   341   int count = 0;
   342   const InstanceKlass* const ik = InstanceKlass::cast((Klass*)klass);
   343   const int len = ik->methods()->length();
   344   for (int i = 0; i < len; ++i) {
   345     MethodPtr method = ik->methods()->at(i);
   346     if (_method_flag_predicate(method)) {
   347       SymbolEntryPtr entry = this->_artifacts->map_symbol(method->name());
   348       assert(entry != NULL, "invariant");
   349       if (_unique_predicate(entry->id())) {
   350         count += write__artifact__symbol__entry__(this->_writer, entry);
   351       }
   352       entry = this->_artifacts->map_symbol(method->signature());
   353       assert(entry != NULL, "invariant");
   354       if (_unique_predicate(entry->id())) {
   355         count += write__artifact__symbol__entry__(this->_writer, entry);
   356       }
   357     }
   358   }
   359   return count;
   360 }
   362 typedef KlassSymbolWriterImpl<LeakPredicate> LeakKlassSymbolWriterImpl;
   363 typedef JfrArtifactWriterHost<LeakKlassSymbolWriterImpl, TYPE_SYMBOL> LeakKlassSymbolWriter;
   365 class ClearKlassAndMethods {
   366  private:
   367   ClearArtifact<KlassPtr> _clear_klass_tag_bits;
   368   ClearArtifact<MethodPtr> _clear_method_flag;
   369   MethodUsedPredicate<false> _method_used_predicate;
   371  public:
   372   ClearKlassAndMethods(bool class_unload) : _clear_klass_tag_bits(class_unload),
   373                                             _clear_method_flag(class_unload),
   374                                             _method_used_predicate(class_unload) {}
   375   bool operator()(KlassPtr klass) {
   376     if (_method_used_predicate(klass)) {
   377       const InstanceKlass* ik = InstanceKlass::cast((Klass*)klass);
   378       const int len = ik->methods()->length();
   379       for (int i = 0; i < len; ++i) {
   380         MethodPtr method = ik->methods()->at(i);
   381         _clear_method_flag(method);
   382       }
   383     }
   384     _clear_klass_tag_bits(klass);
   385     return true;
   386   }
   387 };
   389 typedef CompositeFunctor<KlassPtr,
   390                          TagLeakpKlassArtifact,
   391                          LeakKlassWriter> LeakpKlassArtifactTagging;
   393 typedef CompositeFunctor<KlassPtr,
   394                          LeakpKlassArtifactTagging,
   395                          KlassWriter> CompositeKlassWriter;
   397 typedef CompositeFunctor<KlassPtr,
   398                          CompositeKlassWriter,
   399                          KlassArtifactRegistrator> CompositeKlassWriterRegistration;
   401 typedef CompositeFunctor<KlassPtr,
   402                          KlassWriter,
   403                          KlassArtifactRegistrator> KlassWriterRegistration;
   405 typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
   406 typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
   408 /*
   409  * Composite operation
   410  *
   411  * TagLeakpKlassArtifact ->
   412  *   LeakpPredicate ->
   413  *     LeakpKlassWriter ->
   414  *       KlassPredicate ->
   415  *         KlassWriter ->
   416  *           KlassWriterRegistration
   417  */
   418 void JfrTypeSet::write_klass_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
   419   assert(!_artifacts->has_klass_entries(), "invariant");
   420   KlassArtifactRegistrator reg(_artifacts);
   421   KlassWriter kw(writer, _artifacts, _class_unload);
   422   KlassWriterRegistration kwr(&kw, &reg);
   423   if (leakp_writer == NULL) {
   424     KlassCallback callback(&kwr);
   425     _subsystem_callback = &callback;
   426     do_klasses();
   427     return;
   428   }
   429   TagLeakpKlassArtifact tagging(_class_unload);
   430   LeakKlassWriter lkw(leakp_writer, _artifacts, _class_unload);
   431   LeakpKlassArtifactTagging lpkat(&tagging, &lkw);
   432   CompositeKlassWriter ckw(&lpkat, &kw);
   433   CompositeKlassWriterRegistration ckwr(&ckw, &reg);
   434   CompositeKlassCallback callback(&ckwr);
   435   _subsystem_callback = &callback;
   436   do_klasses();
   437 }
   439 typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
   440 typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
   441 typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
   442 typedef JfrArtifactCallbackHost<CldPtr, CldWriterWithClear> CldCallback;
   443 typedef JfrArtifactCallbackHost<CldPtr, CompositeCldWriterWithClear> CompositeCldCallback;
   445 class CldFieldSelector {
   446  public:
   447   typedef CldPtr TypePtr;
   448   static TypePtr select(KlassPtr klass) {
   449     assert(klass != NULL, "invariant");
   450     CldPtr cld = klass->class_loader_data();
   451     return cld->is_anonymous() ? NULL : cld;
   452   }
   453 };
   455 typedef KlassToFieldEnvelope<CldFieldSelector, CldWriterWithClear> KlassCldWriterWithClear;
   456 typedef KlassToFieldEnvelope<CldFieldSelector, CompositeCldWriterWithClear> KlassCompositeCldWriterWithClear;
   458 /*
   459  * Composite operation
   460  *
   461  * LeakpClassLoaderWriter ->
   462  *   ClassLoaderWriter ->
   463  *     ClearArtifact<ClassLoaderData>
   464  */
   465 void JfrTypeSet::write_class_loader_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
   466   assert(_artifacts->has_klass_entries(), "invariant");
   467   ClearArtifact<CldPtr> clear(_class_unload);
   468   CldWriter cldw(writer, _artifacts, _class_unload);
   469   if (leakp_writer == NULL) {
   470     CldWriterWithClear cldwwc(&cldw, &clear);
   471     KlassCldWriterWithClear kcldwwc(&cldwwc);
   472     _artifacts->iterate_klasses(kcldwwc);
   473     CldCallback callback(&cldwwc);
   474     _subsystem_callback = &callback;
   475     do_class_loaders();
   476     return;
   477   }
   478   LeakCldWriter lcldw(leakp_writer, _artifacts, _class_unload);
   479   CompositeCldWriter ccldw(&lcldw, &cldw);
   480   CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
   481   KlassCompositeCldWriterWithClear kcclwwc(&ccldwwc);
   482   _artifacts->iterate_klasses(kcclwwc);
   483   CompositeCldCallback callback(&ccldwwc);
   484   _subsystem_callback = &callback;
   485   do_class_loaders();
   486 }
   488 template <bool predicate_bool, typename MethodFunctor>
   489 class MethodIteratorHost {
   490  private:
   491   MethodFunctor _method_functor;
   492   MethodUsedPredicate<predicate_bool> _method_used_predicate;
   493   MethodFlagPredicate _method_flag_predicate;
   495  public:
   496   MethodIteratorHost(JfrCheckpointWriter* writer,
   497                      JfrArtifactSet* artifacts,
   498                      bool class_unload,
   499                      bool skip_header = false) :
   500     _method_functor(writer, artifacts, class_unload, skip_header),
   501     _method_used_predicate(class_unload),
   502     _method_flag_predicate(class_unload) {}
   504   bool operator()(KlassPtr klass) {
   505     if (_method_used_predicate(klass)) {
   506       assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
   507       const InstanceKlass* ik = InstanceKlass::cast((Klass*)klass);
   508       const int len = ik->methods()->length();
   509       for (int i = 0; i < len; ++i) {
   510         MethodPtr method = ik->methods()->at(i);
   511         if (_method_flag_predicate(method)) {
   512           _method_functor(method);
   513         }
   514       }
   515     }
   516     return true;
   517   }
   519   int count() const { return _method_functor.count(); }
   520   void add(int count) { _method_functor.add(count); }
   521 };
   523 typedef MethodIteratorHost<true /*leakp */,  MethodWriterImpl> LeakMethodWriter;
   524 typedef MethodIteratorHost<false, MethodWriterImpl> MethodWriter;
   525 typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
   527 /*
   528  * Composite operation
   529  *
   530  * LeakpMethodWriter ->
   531  *   MethodWriter
   532  */
   533 void JfrTypeSet::write_method_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
   534   assert(_artifacts->has_klass_entries(), "invariant");
   535   MethodWriter mw(writer, _artifacts, _class_unload);
   536   if (leakp_writer == NULL) {
   537     _artifacts->iterate_klasses(mw);
   538     return;
   539   }
   540   LeakMethodWriter lpmw(leakp_writer, _artifacts, _class_unload);
   541   CompositeMethodWriter cmw(&lpmw, &mw);
   542   _artifacts->iterate_klasses(cmw);
   543 }
   544 static void write_symbols_leakp(JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
   545   assert(leakp_writer != NULL, "invariant");
   546   assert(artifacts != NULL, "invariant");
   547   LeakKlassSymbolWriter lpksw(leakp_writer, artifacts, class_unload);
   548   artifacts->iterate_klasses(lpksw);
   549 }
   550 static void write_symbols(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
   551   assert(writer != NULL, "invariant");
   552   assert(artifacts != NULL, "invariant");
   553   if (leakp_writer != NULL) {
   554     write_symbols_leakp(leakp_writer, artifacts, class_unload);
   555   }
   556   // iterate all registered symbols
   557   SymbolEntryWriter symbol_writer(writer, artifacts, class_unload);
   558   artifacts->iterate_symbols(symbol_writer);
   559   CStringEntryWriter cstring_writer(writer, artifacts, class_unload, true); // skip header
   560   artifacts->iterate_cstrings(cstring_writer);
   561   symbol_writer.add(cstring_writer.count());
   562 }
   564 bool JfrTypeSet::_class_unload = false;
   565 JfrArtifactSet* JfrTypeSet::_artifacts = NULL;
   566 JfrArtifactClosure* JfrTypeSet::_subsystem_callback = NULL;
   568 void JfrTypeSet::write_symbol_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
   569   assert(writer != NULL, "invariant");
   570   assert(_artifacts->has_klass_entries(), "invariant");
   571   write_symbols(writer, leakp_writer, _artifacts, _class_unload);
   572 }
   574 void JfrTypeSet::do_unloaded_klass(Klass* klass) {
   575   assert(klass != NULL, "invariant");
   576   assert(_subsystem_callback != NULL, "invariant");
   577   if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) {
   578     JfrEventClasses::increment_unloaded_event_class();
   579   }
   580   if (USED_THIS_EPOCH(klass)) { // includes leakp subset
   581     _subsystem_callback->do_artifact(klass);
   582     return;
   583   }
   584   if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
   585     SET_LEAKP_USED_THIS_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
   586     _subsystem_callback->do_artifact(klass);
   587   }
   588 }
   590 void JfrTypeSet::do_klass(Klass* klass) {
   591   assert(klass != NULL, "invariant");
   592   assert(_subsystem_callback != NULL, "invariant");
   593   if (USED_PREV_EPOCH(klass)) { // includes leakp subset
   594     _subsystem_callback->do_artifact(klass);
   595     return;
   596   }
   597   if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
   598     SET_LEAKP_USED_PREV_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
   599     _subsystem_callback->do_artifact(klass);
   600   }
   601 }
   603 void JfrTypeSet::do_klasses() {
   604   if (_class_unload) {
   605     ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass);
   606     return;
   607   }
   608   ClassLoaderDataGraph::classes_do(&do_klass);
   609 }
   611 void JfrTypeSet::do_unloaded_class_loader_data(ClassLoaderData* cld) {
   612   assert(_subsystem_callback != NULL, "invariant");
   613   if (ANY_USED_THIS_EPOCH(cld)) { // includes leakp subset
   614     _subsystem_callback->do_artifact(cld);
   615   }
   616 }
   618 void JfrTypeSet::do_class_loader_data(ClassLoaderData* cld) {
   619   assert(_subsystem_callback != NULL, "invariant");
   620   if (ANY_USED_PREV_EPOCH(cld)) { // includes leakp subset
   621     _subsystem_callback->do_artifact(cld);
   622   }
   623 }
   625 class CLDCallback : public CLDClosure {
   626  private:
   627   bool _class_unload;
   628  public:
   629   CLDCallback(bool class_unload) : _class_unload(class_unload) {}
   630   void do_cld(ClassLoaderData* cld) {
   631      assert(cld != NULL, "invariant");
   632     if (cld->is_anonymous()) {
   633       return;
   634     }
   635     if (_class_unload) {
   636       JfrTypeSet::do_unloaded_class_loader_data(cld);
   637       return;
   638     }
   639     JfrTypeSet::do_class_loader_data(cld);
   640   }
   641 };
   643 void JfrTypeSet::do_class_loaders() {
   644   CLDCallback cld_cb(_class_unload);
   645   if (_class_unload) {
   646     ClassLoaderDataGraph::cld_unloading_do(&cld_cb);
   647     return;
   648   }
   649   ClassLoaderDataGraph::cld_do(&cld_cb);
   650 }
   652 static void clear_artifacts(JfrArtifactSet* artifacts,
   653                             bool class_unload) {
   654   assert(artifacts != NULL, "invariant");
   655   assert(artifacts->has_klass_entries(), "invariant");
   657   // untag
   658   ClearKlassAndMethods clear(class_unload);
   659   artifacts->iterate_klasses(clear);
   660   artifacts->clear();
   661 }
   663 /**
   664  * Write all "tagged" (in-use) constant artifacts and their dependencies.
   665  */
   666 void JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload) {
   667   assert(writer != NULL, "invariant");
   668   ResourceMark rm;
   669   // initialization begin
   670   _class_unload = class_unload;
   671   ++checkpoint_id;
   672   if (_artifacts == NULL) {
   673     _artifacts = new JfrArtifactSet(class_unload);
   674     _subsystem_callback = NULL;
   675   } else {
   676     _artifacts->initialize(class_unload);
   677     _subsystem_callback = NULL;
   678   }
   679   assert(_artifacts != NULL, "invariant");
   680   assert(!_artifacts->has_klass_entries(), "invariant");
   681   assert(_subsystem_callback == NULL, "invariant");
   682   // initialization complete
   684   // write order is important because an individual write step
   685   // might tag an artifact to be written in a subsequent step
   686   write_klass_constants(writer, leakp_writer);
   687   if (_artifacts->has_klass_entries()) {
   688     write_class_loader_constants(writer, leakp_writer);
   689     write_method_constants(writer, leakp_writer);
   690     write_symbol_constants(writer, leakp_writer);
   691     clear_artifacts(_artifacts, class_unload);
   692   }
   693 }

mercurial