Mon, 29 Jun 2020 21:30:26 +0100
Merge
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)))
54 #define CREATE_PACKAGE_ID(pkg_id) (((u8)((checkpoint_id << 24) | pkg_id)))
56 typedef const Klass* KlassPtr;
57 typedef const ClassLoaderData* CldPtr;
58 typedef const Method* MethodPtr;
59 typedef const Symbol* SymbolPtr;
60 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
61 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
63 inline uintptr_t package_name_hash(const char *s) {
64 uintptr_t val = 0;
65 while (*s != 0) {
66 val = *s++ + 31 * val;
67 }
68 return val;
69 }
71 static traceid package_id(KlassPtr klass, JfrArtifactSet* artifacts) {
72 assert(klass != NULL, "invariant");
73 char* klass_name = klass->name()->as_C_string(); // uses ResourceMark declared in JfrTypeSet::serialize()
74 const char* pkg_name = ClassLoader::package_from_name(klass_name, NULL);
75 if (pkg_name == NULL) {
76 return 0;
77 }
78 return CREATE_PACKAGE_ID(artifacts->markPackage(pkg_name, package_name_hash(pkg_name)));
79 }
81 static traceid cld_id(CldPtr cld) {
82 assert(cld != NULL, "invariant");
83 return cld->is_anonymous() ? 0 : TRACE_ID(cld);
84 }
86 static void tag_leakp_klass_artifacts(KlassPtr k, bool class_unload) {
87 assert(k != NULL, "invariant");
88 CldPtr cld = k->class_loader_data();
89 assert(cld != NULL, "invariant");
90 if (!cld->is_anonymous()) {
91 tag_leakp_artifact(cld, class_unload);
92 }
93 }
95 class TagLeakpKlassArtifact {
96 bool _class_unload;
97 public:
98 TagLeakpKlassArtifact(bool class_unload) : _class_unload(class_unload) {}
99 bool operator()(KlassPtr klass) {
100 if (_class_unload) {
101 if (LEAKP_USED_THIS_EPOCH(klass)) {
102 tag_leakp_klass_artifacts(klass, _class_unload);
103 }
104 } else {
105 if (LEAKP_USED_PREV_EPOCH(klass)) {
106 tag_leakp_klass_artifacts(klass, _class_unload);
107 }
108 }
109 return true;
110 }
111 };
113 /*
114 * In C++03, functions used as template parameters must have external linkage;
115 * this restriction was removed in C++11. Change back to "static" and
116 * rename functions when C++11 becomes available.
117 *
118 * The weird naming is an effort to decrease the risk of name clashes.
119 */
121 int write__artifact__klass(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
122 assert(writer != NULL, "invariant");
123 assert(artifacts != NULL, "invariant");
124 assert(k != NULL, "invariant");
125 KlassPtr klass = (KlassPtr)k;
126 traceid pkg_id = 0;
127 KlassPtr theklass = klass;
128 if (theklass->oop_is_objArray()) {
129 const ObjArrayKlass* obj_arr_klass = ObjArrayKlass::cast((Klass*)klass);
130 theklass = obj_arr_klass->bottom_klass();
131 }
132 if (theklass->oop_is_instance()) {
133 pkg_id = package_id(theklass, artifacts);
134 } else {
135 assert(theklass->oop_is_typeArray(), "invariant");
136 }
137 const traceid symbol_id = artifacts->mark(klass);
138 assert(symbol_id > 0, "need to have an address for symbol!");
139 writer->write(TRACE_ID(klass));
140 writer->write(cld_id(klass->class_loader_data()));
141 writer->write((traceid)CREATE_SYMBOL_ID(symbol_id));
142 writer->write(pkg_id);
143 writer->write((s4)klass->access_flags().get_flags());
144 return 1;
145 }
147 typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
148 typedef JfrPredicatedArtifactWriterImplHost<KlassPtr, LeakKlassPredicate, write__artifact__klass> LeakKlassWriterImpl;
149 typedef JfrArtifactWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
150 typedef JfrArtifactWriterImplHost<KlassPtr, write__artifact__klass> KlassWriterImpl;
151 typedef JfrArtifactWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
153 int write__artifact__method(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
154 assert(writer != NULL, "invariant");
155 assert(artifacts != NULL, "invariant");
156 assert(m != NULL, "invariant");
157 MethodPtr method = (MethodPtr)m;
158 const traceid method_name_symbol_id = artifacts->mark(method->name());
159 assert(method_name_symbol_id > 0, "invariant");
160 const traceid method_sig_symbol_id = artifacts->mark(method->signature());
161 assert(method_sig_symbol_id > 0, "invariant");
162 KlassPtr klass = method->method_holder();
163 assert(klass != NULL, "invariant");
164 assert(METHOD_USED_ANY_EPOCH(klass), "invariant");
165 writer->write((u8)METHOD_ID(klass, method));
166 writer->write((u8)TRACE_ID(klass));
167 writer->write((u8)CREATE_SYMBOL_ID(method_name_symbol_id));
168 writer->write((u8)CREATE_SYMBOL_ID(method_sig_symbol_id));
169 writer->write((u2)method->access_flags().get_flags());
170 writer->write(const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0);
171 return 1;
172 }
174 typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget;
175 typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
177 int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) {
178 assert(writer != NULL, "invariant");
179 assert(artifacts != NULL, "invariant");
180 assert(p != NULL, "invariant");
182 CStringEntryPtr entry = (CStringEntryPtr)p;
183 const traceid package_name_symbol_id = artifacts->mark(entry->value(), package_name_hash(entry->value()));
184 assert(package_name_symbol_id > 0, "invariant");
185 writer->write((traceid)CREATE_PACKAGE_ID(entry->id()));
186 writer->write((traceid)CREATE_SYMBOL_ID(package_name_symbol_id));
187 writer->write((bool)true); // exported
188 return 1;
189 }
191 int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) {
192 assert(c != NULL, "invariant");
193 CldPtr cld = (CldPtr)c;
194 assert(!cld->is_anonymous(), "invariant");
195 const traceid cld_id = TRACE_ID(cld);
196 // class loader type
197 const Klass* class_loader_klass = cld->class_loader() != NULL ? cld->class_loader()->klass() : NULL;
198 if (class_loader_klass == NULL) {
199 // (primordial) boot class loader
200 writer->write(cld_id); // class loader instance id
201 writer->write((traceid)0); // class loader type id (absence of)
202 writer->write((traceid)CREATE_SYMBOL_ID(1)); // 1 maps to synthetic name -> "bootstrap"
203 } else {
204 Symbol* symbol_name = class_loader_klass->name();
205 const traceid symbol_name_id = symbol_name != NULL ? artifacts->mark(symbol_name) : 0;
206 writer->write(cld_id); // class loader instance id
207 writer->write(TRACE_ID(class_loader_klass)); // class loader type id
208 writer->write(symbol_name_id == 0 ? (traceid)0 :
209 (traceid)CREATE_SYMBOL_ID(symbol_name_id)); // class loader instance name
210 }
211 return 1;
212 }
214 typedef LeakPredicate<CldPtr> LeakCldPredicate;
215 int _compare_cld_ptr_(CldPtr const& lhs, CldPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
216 typedef UniquePredicate<CldPtr, _compare_cld_ptr_> CldPredicate;
217 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, LeakCldPredicate, write__artifact__classloader> LeakCldWriterImpl;
218 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, CldPredicate, write__artifact__classloader> CldWriterImpl;
219 typedef JfrArtifactWriterHost<LeakCldWriterImpl, TYPE_CLASSLOADER> LeakCldWriter;
220 typedef JfrArtifactWriterHost<CldWriterImpl, TYPE_CLASSLOADER> CldWriter;
222 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
224 static int write__artifact__symbol__entry__(JfrCheckpointWriter* writer,
225 SymbolEntryPtr entry) {
226 assert(writer != NULL, "invariant");
227 assert(entry != NULL, "invariant");
228 ResourceMark rm;
229 writer->write(CREATE_SYMBOL_ID(entry->id()));
230 writer->write(entry->value()->as_C_string());
231 return 1;
232 }
234 int write__artifact__symbol__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
235 assert(e != NULL, "invariant");
236 return write__artifact__symbol__entry__(writer, (SymbolEntryPtr)e);
237 }
239 typedef JfrArtifactWriterImplHost<SymbolEntryPtr, write__artifact__symbol__entry> SymbolEntryWriterImpl;
240 typedef JfrArtifactWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
242 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
244 static int write__artifact__cstring__entry__(JfrCheckpointWriter* writer, CStringEntryPtr entry) {
245 assert(writer != NULL, "invariant");
246 assert(entry != NULL, "invariant");
247 writer->write(CREATE_SYMBOL_ID(entry->id()));
248 writer->write(entry->value());
249 return 1;
250 }
252 int write__artifact__cstring__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
253 assert(e != NULL, "invariant");
254 return write__artifact__cstring__entry__(writer, (CStringEntryPtr)e);
255 }
257 typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__cstring__entry> CStringEntryWriterImpl;
258 typedef JfrArtifactWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
260 int write__artifact__klass__symbol(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
261 assert(writer != NULL, "invariant");
262 assert(artifacts != NULL, "invaiant");
263 assert(k != NULL, "invariant");
264 const InstanceKlass* const ik = (const InstanceKlass*)k;
265 if (ik->is_anonymous()) {
266 CStringEntryPtr entry =
267 artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
268 assert(entry != NULL, "invariant");
269 return write__artifact__cstring__entry__(writer, entry);
270 }
272 SymbolEntryPtr entry = artifacts->map_symbol(JfrSymbolId::regular_klass_name_hash_code(ik));
273 return write__artifact__symbol__entry__(writer, entry);
274 }
276 int _compare_traceid_(const traceid& lhs, const traceid& rhs) {
277 return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
278 }
280 template <template <typename> class Predicate>
281 class KlassSymbolWriterImpl {
282 private:
283 JfrCheckpointWriter* _writer;
284 JfrArtifactSet* _artifacts;
285 Predicate<KlassPtr> _predicate;
286 MethodUsedPredicate<true> _method_used_predicate;
287 MethodFlagPredicate _method_flag_predicate;
288 UniquePredicate<traceid, _compare_traceid_> _unique_predicate;
290 int klass_symbols(KlassPtr klass);
291 int class_loader_symbols(CldPtr cld);
292 int method_symbols(KlassPtr klass);
294 public:
295 typedef KlassPtr Type;
296 KlassSymbolWriterImpl(JfrCheckpointWriter* writer,
297 JfrArtifactSet* artifacts,
298 bool class_unload) : _writer(writer),
299 _artifacts(artifacts),
300 _predicate(class_unload),
301 _method_used_predicate(class_unload),
302 _method_flag_predicate(class_unload),
303 _unique_predicate(class_unload) {}
305 int operator()(KlassPtr klass) {
306 assert(klass != NULL, "invariant");
307 int count = 0;
308 if (_predicate(klass)) {
309 count += klass_symbols(klass);
310 CldPtr cld = klass->class_loader_data();
311 assert(cld != NULL, "invariant");
312 if (!cld->is_anonymous()) {
313 count += class_loader_symbols(cld);
314 }
315 if (_method_used_predicate(klass)) {
316 count += method_symbols(klass);
317 }
318 }
319 return count;
320 }
321 };
323 template <template <typename> class Predicate>
324 int KlassSymbolWriterImpl<Predicate>::klass_symbols(KlassPtr klass) {
325 assert(klass != NULL, "invariant");
326 assert(_predicate(klass), "invariant");
327 const InstanceKlass* const ik = (const InstanceKlass*)klass;
328 if (ik->is_anonymous()) {
329 CStringEntryPtr entry =
330 this->_artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
331 assert(entry != NULL, "invariant");
332 return _unique_predicate(entry->id()) ? write__artifact__cstring__entry__(this->_writer, entry) : 0;
333 }
334 SymbolEntryPtr entry = this->_artifacts->map_symbol(ik->name());
335 assert(entry != NULL, "invariant");
336 return _unique_predicate(entry->id()) ? write__artifact__symbol__entry__(this->_writer, entry) : 0;
337 }
339 template <template <typename> class Predicate>
340 int KlassSymbolWriterImpl<Predicate>::class_loader_symbols(CldPtr cld) {
341 assert(cld != NULL, "invariant");
342 assert(!cld->is_anonymous(), "invariant");
343 int count = 0;
344 // class loader type
345 const Klass* class_loader_klass = cld->class_loader() != NULL ? cld->class_loader()->klass() : NULL;
346 if (class_loader_klass == NULL) {
347 // (primordial) boot class loader
348 CStringEntryPtr entry = this->_artifacts->map_cstring(0);
349 assert(entry != NULL, "invariant");
350 assert(strncmp(entry->literal(),
351 BOOTSTRAP_LOADER_NAME,
352 BOOTSTRAP_LOADER_NAME_LEN) == 0, "invariant");
353 if (_unique_predicate(entry->id())) {
354 count += write__artifact__cstring__entry__(this->_writer, entry);
355 }
356 } else {
357 const Symbol* class_loader_name = class_loader_klass->name()/* XXX TODO cld->name()*/;
358 if (class_loader_name != NULL) {
359 SymbolEntryPtr entry = this->_artifacts->map_symbol(class_loader_name);
360 assert(entry != NULL, "invariant");
361 if (_unique_predicate(entry->id())) {
362 count += write__artifact__symbol__entry__(this->_writer, entry);
363 }
364 }
365 }
366 return count;
367 }
369 template <template <typename> class Predicate>
370 int KlassSymbolWriterImpl<Predicate>::method_symbols(KlassPtr klass) {
371 assert(_predicate(klass), "invariant");
372 assert(_method_used_predicate(klass), "invariant");
373 assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
374 int count = 0;
375 const InstanceKlass* const ik = InstanceKlass::cast((Klass*)klass);
376 const int len = ik->methods()->length();
377 for (int i = 0; i < len; ++i) {
378 MethodPtr method = ik->methods()->at(i);
379 if (_method_flag_predicate(method)) {
380 SymbolEntryPtr entry = this->_artifacts->map_symbol(method->name());
381 assert(entry != NULL, "invariant");
382 if (_unique_predicate(entry->id())) {
383 count += write__artifact__symbol__entry__(this->_writer, entry);
384 }
385 entry = this->_artifacts->map_symbol(method->signature());
386 assert(entry != NULL, "invariant");
387 if (_unique_predicate(entry->id())) {
388 count += write__artifact__symbol__entry__(this->_writer, entry);
389 }
390 }
391 }
392 return count;
393 }
395 typedef KlassSymbolWriterImpl<LeakPredicate> LeakKlassSymbolWriterImpl;
396 typedef JfrArtifactWriterHost<LeakKlassSymbolWriterImpl, TYPE_SYMBOL> LeakKlassSymbolWriter;
398 class ClearKlassAndMethods {
399 private:
400 ClearArtifact<KlassPtr> _clear_klass_tag_bits;
401 ClearArtifact<MethodPtr> _clear_method_flag;
402 MethodUsedPredicate<false> _method_used_predicate;
404 public:
405 ClearKlassAndMethods(bool class_unload) : _clear_klass_tag_bits(class_unload),
406 _clear_method_flag(class_unload),
407 _method_used_predicate(class_unload) {}
408 bool operator()(KlassPtr klass) {
409 if (_method_used_predicate(klass)) {
410 const InstanceKlass* ik = InstanceKlass::cast((Klass*)klass);
411 const int len = ik->methods()->length();
412 for (int i = 0; i < len; ++i) {
413 MethodPtr method = ik->methods()->at(i);
414 _clear_method_flag(method);
415 }
416 }
417 _clear_klass_tag_bits(klass);
418 return true;
419 }
420 };
422 typedef CompositeFunctor<KlassPtr,
423 TagLeakpKlassArtifact,
424 LeakKlassWriter> LeakpKlassArtifactTagging;
426 typedef CompositeFunctor<KlassPtr,
427 LeakpKlassArtifactTagging,
428 KlassWriter> CompositeKlassWriter;
430 typedef CompositeFunctor<KlassPtr,
431 CompositeKlassWriter,
432 KlassArtifactRegistrator> CompositeKlassWriterRegistration;
434 typedef CompositeFunctor<KlassPtr,
435 KlassWriter,
436 KlassArtifactRegistrator> KlassWriterRegistration;
438 typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
439 typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
441 /*
442 * Composite operation
443 *
444 * TagLeakpKlassArtifact ->
445 * LeakpPredicate ->
446 * LeakpKlassWriter ->
447 * KlassPredicate ->
448 * KlassWriter ->
449 * KlassWriterRegistration
450 */
451 void JfrTypeSet::write_klass_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
452 assert(!_artifacts->has_klass_entries(), "invariant");
453 KlassArtifactRegistrator reg(_artifacts);
454 KlassWriter kw(writer, _artifacts, _class_unload);
455 KlassWriterRegistration kwr(&kw, ®);
456 if (leakp_writer == NULL) {
457 KlassCallback callback(&kwr);
458 _subsystem_callback = &callback;
459 do_klasses();
460 return;
461 }
462 TagLeakpKlassArtifact tagging(_class_unload);
463 LeakKlassWriter lkw(leakp_writer, _artifacts, _class_unload);
464 LeakpKlassArtifactTagging lpkat(&tagging, &lkw);
465 CompositeKlassWriter ckw(&lpkat, &kw);
466 CompositeKlassWriterRegistration ckwr(&ckw, ®);
467 CompositeKlassCallback callback(&ckwr);
468 _subsystem_callback = &callback;
469 do_klasses();
470 }
472 typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__package> PackageEntryWriterImpl;
473 typedef JfrArtifactWriterHost<PackageEntryWriterImpl, TYPE_PACKAGE> PackageEntryWriter;
475 void JfrTypeSet::write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
476 assert(_artifacts->has_klass_entries(), "invariant");
477 assert(writer != NULL, "invariant");
478 // below jdk9 there is no oop for packages, so nothing to do with leakp_writer
479 // just write packages
480 PackageEntryWriter pw(writer, _artifacts, _class_unload);
481 _artifacts->iterate_packages(pw);
482 }
484 typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
485 typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
486 typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
487 typedef JfrArtifactCallbackHost<CldPtr, CldWriterWithClear> CldCallback;
488 typedef JfrArtifactCallbackHost<CldPtr, CompositeCldWriterWithClear> CompositeCldCallback;
490 class CldFieldSelector {
491 public:
492 typedef CldPtr TypePtr;
493 static TypePtr select(KlassPtr klass) {
494 assert(klass != NULL, "invariant");
495 CldPtr cld = klass->class_loader_data();
496 return cld->is_anonymous() ? NULL : cld;
497 }
498 };
500 typedef KlassToFieldEnvelope<CldFieldSelector, CldWriterWithClear> KlassCldWriterWithClear;
501 typedef KlassToFieldEnvelope<CldFieldSelector, CompositeCldWriterWithClear> KlassCompositeCldWriterWithClear;
503 /*
504 * Composite operation
505 *
506 * LeakpClassLoaderWriter ->
507 * ClassLoaderWriter ->
508 * ClearArtifact<ClassLoaderData>
509 */
510 void JfrTypeSet::write_class_loader_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
511 assert(_artifacts->has_klass_entries(), "invariant");
512 ClearArtifact<CldPtr> clear(_class_unload);
513 CldWriter cldw(writer, _artifacts, _class_unload);
514 if (leakp_writer == NULL) {
515 CldWriterWithClear cldwwc(&cldw, &clear);
516 KlassCldWriterWithClear kcldwwc(&cldwwc);
517 _artifacts->iterate_klasses(kcldwwc);
518 CldCallback callback(&cldwwc);
519 _subsystem_callback = &callback;
520 do_class_loaders();
521 return;
522 }
523 LeakCldWriter lcldw(leakp_writer, _artifacts, _class_unload);
524 CompositeCldWriter ccldw(&lcldw, &cldw);
525 CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
526 KlassCompositeCldWriterWithClear kcclwwc(&ccldwwc);
527 _artifacts->iterate_klasses(kcclwwc);
528 CompositeCldCallback callback(&ccldwwc);
529 _subsystem_callback = &callback;
530 do_class_loaders();
531 }
533 template <bool predicate_bool, typename MethodFunctor>
534 class MethodIteratorHost {
535 private:
536 MethodFunctor _method_functor;
537 MethodUsedPredicate<predicate_bool> _method_used_predicate;
538 MethodFlagPredicate _method_flag_predicate;
540 public:
541 MethodIteratorHost(JfrCheckpointWriter* writer,
542 JfrArtifactSet* artifacts,
543 bool class_unload,
544 bool skip_header = false) :
545 _method_functor(writer, artifacts, class_unload, skip_header),
546 _method_used_predicate(class_unload),
547 _method_flag_predicate(class_unload) {}
549 bool operator()(KlassPtr klass) {
550 if (_method_used_predicate(klass)) {
551 assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
552 const InstanceKlass* ik = InstanceKlass::cast((Klass*)klass);
553 const int len = ik->methods()->length();
554 for (int i = 0; i < len; ++i) {
555 MethodPtr method = ik->methods()->at(i);
556 if (_method_flag_predicate(method)) {
557 _method_functor(method);
558 }
559 }
560 }
561 return true;
562 }
564 int count() const { return _method_functor.count(); }
565 void add(int count) { _method_functor.add(count); }
566 };
568 typedef MethodIteratorHost<true /*leakp */, MethodWriterImpl> LeakMethodWriter;
569 typedef MethodIteratorHost<false, MethodWriterImpl> MethodWriter;
570 typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
572 /*
573 * Composite operation
574 *
575 * LeakpMethodWriter ->
576 * MethodWriter
577 */
578 void JfrTypeSet::write_method_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
579 assert(_artifacts->has_klass_entries(), "invariant");
580 MethodWriter mw(writer, _artifacts, _class_unload);
581 if (leakp_writer == NULL) {
582 _artifacts->iterate_klasses(mw);
583 return;
584 }
585 LeakMethodWriter lpmw(leakp_writer, _artifacts, _class_unload);
586 CompositeMethodWriter cmw(&lpmw, &mw);
587 _artifacts->iterate_klasses(cmw);
588 }
589 static void write_symbols_leakp(JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
590 assert(leakp_writer != NULL, "invariant");
591 assert(artifacts != NULL, "invariant");
592 LeakKlassSymbolWriter lpksw(leakp_writer, artifacts, class_unload);
593 artifacts->iterate_klasses(lpksw);
594 }
595 static void write_symbols(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
596 assert(writer != NULL, "invariant");
597 assert(artifacts != NULL, "invariant");
598 if (leakp_writer != NULL) {
599 write_symbols_leakp(leakp_writer, artifacts, class_unload);
600 }
601 // iterate all registered symbols
602 SymbolEntryWriter symbol_writer(writer, artifacts, class_unload);
603 artifacts->iterate_symbols(symbol_writer);
604 CStringEntryWriter cstring_writer(writer, artifacts, class_unload, true); // skip header
605 artifacts->iterate_cstrings(cstring_writer);
606 symbol_writer.add(cstring_writer.count());
607 }
609 bool JfrTypeSet::_class_unload = false;
610 JfrArtifactSet* JfrTypeSet::_artifacts = NULL;
611 JfrArtifactClosure* JfrTypeSet::_subsystem_callback = NULL;
613 void JfrTypeSet::write_symbol_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
614 assert(writer != NULL, "invariant");
615 assert(_artifacts->has_klass_entries(), "invariant");
616 write_symbols(writer, leakp_writer, _artifacts, _class_unload);
617 }
619 void JfrTypeSet::do_unloaded_klass(Klass* klass) {
620 assert(klass != NULL, "invariant");
621 assert(_subsystem_callback != NULL, "invariant");
622 if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) {
623 JfrEventClasses::increment_unloaded_event_class();
624 }
625 if (USED_THIS_EPOCH(klass)) { // includes leakp subset
626 _subsystem_callback->do_artifact(klass);
627 return;
628 }
629 if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
630 SET_LEAKP_USED_THIS_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
631 _subsystem_callback->do_artifact(klass);
632 }
633 }
635 void JfrTypeSet::do_klass(Klass* klass) {
636 assert(klass != NULL, "invariant");
637 assert(_subsystem_callback != NULL, "invariant");
638 if (USED_PREV_EPOCH(klass)) { // includes leakp subset
639 _subsystem_callback->do_artifact(klass);
640 return;
641 }
642 if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
643 SET_LEAKP_USED_PREV_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
644 _subsystem_callback->do_artifact(klass);
645 }
646 }
648 void JfrTypeSet::do_klasses() {
649 if (_class_unload) {
650 ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass);
651 return;
652 }
653 ClassLoaderDataGraph::classes_do(&do_klass);
654 }
656 void JfrTypeSet::do_unloaded_class_loader_data(ClassLoaderData* cld) {
657 assert(_subsystem_callback != NULL, "invariant");
658 if (ANY_USED_THIS_EPOCH(cld)) { // includes leakp subset
659 _subsystem_callback->do_artifact(cld);
660 }
661 }
663 void JfrTypeSet::do_class_loader_data(ClassLoaderData* cld) {
664 assert(_subsystem_callback != NULL, "invariant");
665 if (ANY_USED_PREV_EPOCH(cld)) { // includes leakp subset
666 _subsystem_callback->do_artifact(cld);
667 }
668 }
670 class CLDCallback : public CLDClosure {
671 private:
672 bool _class_unload;
673 public:
674 CLDCallback(bool class_unload) : _class_unload(class_unload) {}
675 void do_cld(ClassLoaderData* cld) {
676 assert(cld != NULL, "invariant");
677 if (cld->is_anonymous()) {
678 return;
679 }
680 if (_class_unload) {
681 JfrTypeSet::do_unloaded_class_loader_data(cld);
682 return;
683 }
684 JfrTypeSet::do_class_loader_data(cld);
685 }
686 };
688 void JfrTypeSet::do_class_loaders() {
689 CLDCallback cld_cb(_class_unload);
690 if (_class_unload) {
691 ClassLoaderDataGraph::cld_unloading_do(&cld_cb);
692 return;
693 }
694 ClassLoaderDataGraph::cld_do(&cld_cb);
695 }
697 static void clear_artifacts(JfrArtifactSet* artifacts,
698 bool class_unload) {
699 assert(artifacts != NULL, "invariant");
700 assert(artifacts->has_klass_entries(), "invariant");
702 // untag
703 ClearKlassAndMethods clear(class_unload);
704 artifacts->iterate_klasses(clear);
705 artifacts->clear();
706 }
708 /**
709 * Write all "tagged" (in-use) constant artifacts and their dependencies.
710 */
711 void JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload) {
712 assert(writer != NULL, "invariant");
713 ResourceMark rm;
714 // initialization begin
715 _class_unload = class_unload;
716 ++checkpoint_id;
717 if (_artifacts == NULL) {
718 _artifacts = new JfrArtifactSet(class_unload);
719 _subsystem_callback = NULL;
720 } else {
721 _artifacts->initialize(class_unload);
722 _subsystem_callback = NULL;
723 }
724 assert(_artifacts != NULL, "invariant");
725 assert(!_artifacts->has_klass_entries(), "invariant");
726 assert(_subsystem_callback == NULL, "invariant");
727 // initialization complete
729 // write order is important because an individual write step
730 // might tag an artifact to be written in a subsequent step
731 write_klass_constants(writer, leakp_writer);
732 if (_artifacts->has_klass_entries()) {
733 write_package_constants(writer, leakp_writer);
734 write_class_loader_constants(writer, leakp_writer);
735 write_method_constants(writer, leakp_writer);
736 write_symbol_constants(writer, leakp_writer);
737 clear_artifacts(_artifacts, class_unload);
738 }
739 }