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