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

Mon, 29 Jun 2020 21:30:26 +0100

author
andrew
date
Mon, 29 Jun 2020 21:30:26 +0100
changeset 9949
fb74ae591209
parent 9941
45c8de52649c
parent 9926
d20a5f399218
permissions
-rw-r--r--

Merge

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

mercurial