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