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