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