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