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