1 /* 2 * Copyright (c) 2023, 2024, 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 <cds/archiveBuilder.hpp> 26 #include <classfile/systemDictionaryShared.hpp> 27 #include <compiler/compileBroker.hpp> 28 #include "precompiled.hpp" 29 #include "ci/ciEnv.hpp" 30 #include "ci/ciMetadata.hpp" 31 #include "cds/archiveBuilder.hpp" 32 #include "cds/cdsConfig.hpp" 33 #include "cds/metaspaceShared.hpp" 34 #include "cds/methodDataDictionary.hpp" 35 #include "cds/methodProfiler.hpp" 36 #include "cds/runTimeClassInfo.hpp" 37 #include "classfile/classLoaderData.hpp" 38 #include "classfile/compactHashtable.hpp" 39 #include "classfile/javaClasses.hpp" 40 #include "classfile/symbolTable.hpp" 41 #include "classfile/systemDictionaryShared.hpp" 42 #include "compiler/compileTask.hpp" 43 #include "memory/metadataFactory.hpp" 44 #include "memory/metaspaceClosure.hpp" 45 #include "memory/resourceArea.hpp" 46 #include "oops/fieldStreams.inline.hpp" 47 #include "oops/method.hpp" 48 #include "oops/methodCounters.hpp" 49 #include "oops/trainingData.hpp" 50 #include "runtime/arguments.hpp" 51 #include "runtime/fieldDescriptor.inline.hpp" 52 #include "runtime/javaThread.inline.hpp" 53 #include "runtime/jniHandles.inline.hpp" 54 #include "runtime/os.hpp" 55 #include "utilities/growableArray.hpp" 56 #include "utilities/xmlstream.hpp" 57 58 TrainingData::TrainingDataSet TrainingData::_training_data_set(1024, 0x3fffffff); 59 TrainingDataDictionary TrainingData::_archived_training_data_dictionary; 60 TrainingDataDictionary TrainingData::_archived_training_data_dictionary_for_dumping; 61 GrowableArrayCHeap<DumpTimeTrainingDataInfo, mtClassShared>* TrainingData::_dumptime_training_data_dictionary = nullptr; 62 Array<MethodTrainingData*>* TrainingData::_recompilation_schedule = nullptr; 63 Array<MethodTrainingData*>* TrainingData::_recompilation_schedule_for_dumping = nullptr; 64 volatile bool* TrainingData::_recompilation_status = nullptr; 65 int TrainingData::TrainingDataLocker::_lock_mode; 66 67 MethodTrainingData::MethodTrainingData() { 68 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS"); 69 } 70 71 KlassTrainingData::KlassTrainingData() { 72 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS"); 73 } 74 75 CompileTrainingData::CompileTrainingData() : _level(-1), _compile_id(-1) { 76 assert(CDSConfig::is_dumping_static_archive() || UseSharedSpaces, "only for CDS"); 77 } 78 79 void TrainingData::initialize() { 80 // this is a nop if training modes are not enabled 81 if (have_data() || need_data()) { 82 TrainingDataLocker::initialize(); 83 } 84 if (have_data()) { 85 if (_recompilation_schedule != nullptr && _recompilation_schedule->length() > 0) { 86 const int size = _recompilation_schedule->length(); 87 _recompilation_status = NEW_C_HEAP_ARRAY(bool, size, mtCompiler); 88 for (int i = 0; i < size; i++) { 89 _recompilation_status[i] = false; 90 } 91 } 92 } 93 } 94 95 static void verify_archived_entry(TrainingData* td, const TrainingData::Key* k) { 96 ResourceMark rm; 97 guarantee(TrainingData::Key::can_compute_cds_hash(k), "%s %s " INTPTR_FORMAT, 98 (k->name1() != nullptr ? k->name1()->as_C_string() : "(null)"), 99 (k->name2() != nullptr ? k->name2()->as_C_string() : "(null)"), 100 p2i(k->holder())); 101 102 TrainingData* td1 = TrainingData::lookup_archived_training_data(k); 103 guarantee(td == td1, "%s %s " INTPTR_FORMAT ": " INTPTR_FORMAT " != " INTPTR_FORMAT, 104 (k->name1() != nullptr ? k->name1()->as_C_string() : "(null)"), 105 (k->name2() != nullptr ? k->name2()->as_C_string() : "(null)"), 106 p2i(k->holder()), p2i(td), p2i(td1)); 107 } 108 109 void TrainingData::verify() { 110 if (TrainingData::have_data()) { 111 archived_training_data_dictionary()->iterate([&](TrainingData* td) { 112 if (td->is_KlassTrainingData()) { 113 KlassTrainingData* ktd = td->as_KlassTrainingData(); 114 if (ktd->has_holder() && ktd->holder()->is_loaded()) { 115 Key k(ktd->holder()); 116 verify_archived_entry(td, &k); 117 } 118 ktd->verify(); 119 } else if (td->is_MethodTrainingData()) { 120 MethodTrainingData* mtd = td->as_MethodTrainingData(); 121 if (mtd->has_holder() && mtd->holder()->method_holder()->is_loaded()) { 122 Key k(mtd); 123 verify_archived_entry(td, &k); 124 } 125 mtd->verify(); 126 } else if (td->is_CompileTrainingData()) { 127 td->as_CompileTrainingData()->verify(); 128 } 129 }); 130 } 131 } 132 133 134 TrainingData::Key::Key(const KlassTrainingData* klass, Symbol* method_name, Symbol* signature) 135 : Key(method_name, signature, klass) {} 136 137 TrainingData::Key::Key(const InstanceKlass* klass) 138 : Key(klass->name(), klass->class_loader_name_and_id()) { 139 // Often the loader is either null or the string "'app'" (w/ extra quotes). 140 // It can also be "'platform'". 141 } 142 143 TrainingData::Key::Key(const Method* method, KlassTrainingData* holder) 144 : Key(method->name(), method->signature(), holder) 145 { 146 assert(method->method_holder() == holder->holder(), "mismatch"); 147 } 148 149 TrainingData::Key::Key(const MethodTrainingData* method) : Key(method->holder(), method->klass()) {} 150 151 MethodTrainingData* MethodTrainingData::make(const methodHandle& method, 152 bool null_if_not_found) { 153 MethodTrainingData* mtd = nullptr; 154 if (!have_data() && !need_data()) { 155 return mtd; 156 } 157 // Try grabbing the cached value first. 158 MethodCounters* mcs = method->method_counters(); 159 if (mcs != nullptr) { 160 mtd = mcs->method_training_data(); 161 if (mtd != nullptr) { 162 return mtd; 163 } 164 } else { 165 mcs = Method::build_method_counters(Thread::current(), method()); 166 } 167 168 KlassTrainingData* holder = KlassTrainingData::make(method->method_holder(), null_if_not_found); 169 if (holder == nullptr) { 170 return nullptr; // allocation failure 171 } 172 Key key(method->name(), method->signature(), holder); 173 TrainingData* td = have_data()? lookup_archived_training_data(&key) : nullptr; 174 if (td != nullptr) { 175 mtd = td->as_MethodTrainingData(); 176 mtd->refresh_from(method()); 177 method->init_training_data(mtd); // Cache the pointer for next time. 178 return mtd; 179 } else { 180 TrainingDataLocker l; 181 td = training_data_set()->find(&key); 182 if (td == nullptr && null_if_not_found) { 183 return nullptr; 184 } 185 if (td != nullptr) { 186 mtd = td->as_MethodTrainingData(); 187 mtd->refresh_from(method()); 188 method->init_training_data(mtd); // Cache the pointer for next time. 189 return mtd; 190 } 191 } 192 assert(td == nullptr && mtd == nullptr && !null_if_not_found, "Should return if have result"); 193 KlassTrainingData* ktd = KlassTrainingData::make(method->method_holder()); 194 if (ktd != nullptr) { 195 TrainingDataLocker l; 196 td = training_data_set()->find(&key); 197 if (td == nullptr) { 198 mtd = MethodTrainingData::allocate(ktd, method()); 199 if (mtd == nullptr) { 200 return nullptr; // allocation failure 201 } 202 td = training_data_set()->install(mtd); 203 assert(td == mtd, ""); 204 } else { 205 mtd = td->as_MethodTrainingData(); 206 } 207 mtd->refresh_from(method()); 208 method->init_training_data(mtd); 209 } 210 return mtd; 211 } 212 213 void MethodTrainingData::print_on(outputStream* st, bool name_only) const { 214 _klass->print_on(st, true); 215 st->print("."); 216 name()->print_symbol_on(st); 217 signature()->print_symbol_on(st); 218 if (name_only) { 219 return; 220 } 221 if (!has_holder()) { 222 st->print("[SYM]"); 223 } 224 if (_level_mask) { 225 st->print(" LM%d", _level_mask); 226 } 227 st->print(" mc=%p mdo=%p", _final_counters, _final_profile); 228 } 229 230 void MethodTrainingData::refresh_from(const Method* method) { 231 if (method == nullptr || method == _holder) { 232 return; 233 } 234 _holder = method; 235 } 236 237 CompileTrainingData* CompileTrainingData::make(CompileTask* task) { 238 int level = task->comp_level(); 239 int compile_id = task->compile_id(); 240 Thread* thread = Thread::current(); 241 methodHandle m(thread, task->method()); 242 MethodTrainingData* mtd = MethodTrainingData::make(m); 243 if (mtd == nullptr) { 244 return nullptr; // allocation failure 245 } 246 mtd->notice_compilation(level); 247 248 CompileTrainingData* ctd = CompileTrainingData::allocate(mtd, level, compile_id); 249 if (ctd != nullptr) { 250 TrainingDataLocker l; 251 if (mtd->_last_toplevel_compiles[level - 1] != nullptr) { 252 if (mtd->_last_toplevel_compiles[level - 1]->compile_id() < compile_id) { 253 mtd->_last_toplevel_compiles[level - 1]->clear_init_deps(); 254 mtd->_last_toplevel_compiles[level - 1] = ctd; 255 mtd->_highest_top_level = MAX2(mtd->_highest_top_level, level); 256 } 257 } else { 258 mtd->_last_toplevel_compiles[level - 1] = ctd; 259 mtd->_highest_top_level = MAX2(mtd->_highest_top_level, level); 260 } 261 } 262 return ctd; 263 } 264 265 266 void CompileTrainingData::dec_init_deps_left(KlassTrainingData* ktd) { 267 LogStreamHandle(Trace, training) log; 268 if (log.is_enabled()) { 269 log.print("CTD "); print_on(&log); log.cr(); 270 log.print("KTD "); ktd->print_on(&log); log.cr(); 271 } 272 assert(ktd!= nullptr && ktd->has_holder(), ""); 273 assert(_init_deps.contains(ktd), ""); 274 assert(_init_deps_left > 0, ""); 275 276 uint init_deps_left1 = Atomic::sub(&_init_deps_left, 1); 277 278 if (log.is_enabled()) { 279 uint init_deps_left2 = compute_init_deps_left(); 280 log.print("init_deps_left: %d (%d)", init_deps_left1, init_deps_left2); 281 ktd->print_on(&log, true); 282 } 283 } 284 285 uint CompileTrainingData::compute_init_deps_left(bool count_initialized) { 286 int left = 0; 287 for (int i = 0; i < _init_deps.length(); i++) { 288 KlassTrainingData* ktd = _init_deps.at(i); 289 // Ignore symbolic refs and already initialized classes (unless explicitly requested). 290 if (ktd->has_holder()) { 291 InstanceKlass* holder = ktd->holder(); 292 if (!ktd->holder()->is_initialized() || count_initialized) { 293 ++left; 294 } else if (holder->is_shared_unregistered_class()) { 295 Key k(holder); 296 if (!Key::can_compute_cds_hash(&k)) { 297 ++left; // FIXME: !!! init tracking doesn't work well for custom loaders !!! 298 } 299 } 300 } 301 } 302 return left; 303 } 304 305 void CompileTrainingData::print_on(outputStream* st, bool name_only) const { 306 _method->print_on(st, true); 307 st->print("#%dL%d", _compile_id, _level); 308 if (name_only) { 309 return; 310 } 311 #define MAYBE_TIME(Q, _qtime) \ 312 if (_qtime != 0) st->print(" " #Q "%.3f", _qtime) 313 MAYBE_TIME(Q, _qtime); 314 MAYBE_TIME(S, _stime); 315 MAYBE_TIME(E, _etime); 316 if (_init_deps.length() > 0) { 317 if (_init_deps_left > 0) { 318 st->print(" udeps=%d", _init_deps_left); 319 } 320 for (int i = 0, len = _init_deps.length(); i < len; i++) { 321 st->print(" dep:"); 322 _init_deps.at(i)->print_on(st, true); 323 } 324 } 325 } 326 327 void CompileTrainingData::record_compilation_queued(CompileTask* task) { 328 _qtime = tty->time_stamp().seconds(); 329 } 330 void CompileTrainingData::record_compilation_start(CompileTask* task) { 331 _stime = tty->time_stamp().seconds(); 332 } 333 void CompileTrainingData::record_compilation_end(CompileTask* task) { 334 _etime = tty->time_stamp().seconds(); 335 if (task->is_success()) { // record something about the nmethod output 336 _nm_total_size = task->nm_total_size(); 337 } 338 } 339 void CompileTrainingData::notice_inlined_method(CompileTask* task, 340 const methodHandle& method) { 341 MethodTrainingData* mtd = MethodTrainingData::make(method); 342 if (mtd != nullptr) { 343 mtd->notice_compilation(task->comp_level(), true); 344 } 345 } 346 347 void CompileTrainingData::notice_jit_observation(ciEnv* env, ciBaseObject* what) { 348 // A JIT is starting to look at class k. 349 // We could follow the queries that it is making, but it is 350 // simpler to assume, conservatively, that the JIT will 351 // eventually depend on the initialization state of k. 352 CompileTask* task = env->task(); 353 assert(task != nullptr, ""); 354 Method* method = task->method(); 355 InstanceKlass* compiling_klass = method->method_holder(); 356 if (what->is_metadata()) { 357 ciMetadata* md = what->as_metadata(); 358 if (md->is_loaded() && md->is_instance_klass()) { 359 ciInstanceKlass* cik = md->as_instance_klass(); 360 361 if (cik->is_initialized()) { 362 InstanceKlass* ik = md->as_instance_klass()->get_instanceKlass(); 363 KlassTrainingData* ktd = KlassTrainingData::make(ik); 364 assert(ktd != nullptr, ""); 365 // This JIT task is (probably) requesting that ik be initialized, 366 // so add him to my _init_deps list. 367 TrainingDataLocker l; 368 add_init_dep(ktd); 369 } 370 } 371 } 372 } 373 374 void KlassTrainingData::prepare(Visitor& visitor) { 375 if (visitor.is_visited(this)) { 376 return; 377 } 378 visitor.visit(this); 379 ClassLoaderData* loader_data = nullptr; 380 if (_holder != nullptr) { 381 loader_data = _holder->class_loader_data(); 382 } else { 383 loader_data = java_lang_ClassLoader::loader_data(SystemDictionary::java_system_loader()); // default CLD 384 } 385 _comp_deps.prepare(loader_data); 386 } 387 388 void MethodTrainingData::prepare(Visitor& visitor) { 389 if (visitor.is_visited(this)) { 390 return; 391 } 392 visitor.visit(this); 393 klass()->prepare(visitor); 394 if (has_holder()) { 395 _final_counters = holder()->method_counters(); 396 _final_profile = holder()->method_data(); 397 assert(_final_profile == nullptr || _final_profile->method() == holder(), ""); 398 } 399 for (int i = 0; i < CompLevel_count; i++) { 400 CompileTrainingData* ctd = _last_toplevel_compiles[i]; 401 if (ctd != nullptr) { 402 ctd->prepare(visitor); 403 } 404 } 405 } 406 407 void CompileTrainingData::prepare(Visitor& visitor) { 408 if (visitor.is_visited(this)) { 409 return; 410 } 411 visitor.visit(this); 412 method()->prepare(visitor); 413 ClassLoaderData* loader_data = _method->klass()->class_loader_data(); 414 _init_deps.prepare(loader_data); 415 _ci_records.prepare(loader_data); 416 } 417 418 KlassTrainingData* KlassTrainingData::make(InstanceKlass* holder, bool null_if_not_found) { 419 Key key(holder); 420 TrainingData* td = have_data() ? lookup_archived_training_data(&key) : nullptr; 421 KlassTrainingData* ktd = nullptr; 422 if (td != nullptr) { 423 ktd = td->as_KlassTrainingData(); 424 ktd->refresh_from(holder); 425 guarantee(ktd->has_holder() && ktd->holder() == holder, ""); 426 return ktd; 427 } 428 TrainingDataLocker l; 429 td = training_data_set()->find(&key); 430 if (td == nullptr) { 431 if (null_if_not_found) { 432 return nullptr; 433 } 434 ktd = KlassTrainingData::allocate(holder); 435 if (ktd == nullptr) { 436 return nullptr; // allocation failure 437 } 438 td = training_data_set()->install(ktd); 439 assert(ktd == td, ""); 440 } else { 441 ktd = td->as_KlassTrainingData(); 442 } 443 assert(ktd != nullptr, ""); 444 ktd->refresh_from(holder); 445 guarantee(ktd->has_holder() && ktd->holder() == holder, ""); 446 return ktd; 447 } 448 449 void KlassTrainingData::print_on(outputStream* st, bool name_only) const { 450 name()->print_symbol_on(st); 451 if (has_holder()) { 452 switch (holder()->init_state()) { 453 case InstanceKlass::allocated: st->print("[A]"); break; 454 case InstanceKlass::loaded: st->print("[D]"); break; 455 case InstanceKlass::being_linked: st->print("[l]"); break; 456 case InstanceKlass::linked: st->print("[L]"); break; 457 case InstanceKlass::being_initialized: st->print("[i]"); break; 458 case InstanceKlass::fully_initialized: /*st->print("");*/ break; 459 case InstanceKlass::initialization_error: st->print("[E]"); break; 460 default: fatal("unknown state: %d", holder()->init_state()); 461 } 462 if (holder()->is_interface()) { 463 st->print("I"); 464 } 465 } else { 466 st->print("[SYM]"); 467 } 468 if (name_only) { 469 return; 470 } 471 if (_comp_deps.length() > 0) { 472 for (int i = 0, len = _comp_deps.length(); i < len; i++) { 473 st->print(" dep:"); 474 _comp_deps.at(i)->print_on(st, true); 475 } 476 } 477 } 478 479 void KlassTrainingData::refresh_from(const InstanceKlass* klass) { 480 if (!has_holder()) { 481 init_holder(klass); 482 } 483 } 484 485 void KlassTrainingData::init_holder(const InstanceKlass* klass) { 486 if (holder() == klass) { 487 return; // no change to make 488 } 489 490 jobject hmj = _holder_mirror; 491 if (hmj != nullptr) { // clear out previous handle, if any 492 _holder_mirror = nullptr; 493 assert(JNIHandles::is_global_handle(hmj), ""); 494 JNIHandles::destroy_global(hmj); 495 } 496 497 // Keep the klass alive during the training run, unconditionally. 498 // 499 // FIXME: Revisit this decision; we could allow training runs to 500 // unload classes in the normal way. We might use make_weak_global 501 // instead of make_global. 502 // 503 // The data from the training run would mention the name of the 504 // unloaded class (and of its loader). Is it worth the complexity 505 // to track and then unload classes, remembering just their names? 506 507 if (klass != nullptr) { 508 Handle hm(JavaThread::current(), klass->java_mirror()); 509 hmj = JNIHandles::make_global(hm); 510 Atomic::release_store(&_holder_mirror, hmj); 511 } 512 513 Atomic::release_store(&_holder, const_cast<InstanceKlass*>(klass)); 514 assert(holder() == klass, ""); 515 } 516 517 void KlassTrainingData::notice_fully_initialized() { 518 ResourceMark rm; 519 assert(has_holder(), ""); 520 assert(holder()->is_initialized(), "wrong state: %s %s", 521 holder()->name()->as_C_string(), holder()->init_state_name()); 522 523 TrainingDataLocker l; // Not a real lock if we don't collect the data, 524 // that's why we need the atomic decrement below. 525 for (int i = 0; i < comp_dep_count(); i++) { 526 comp_dep(i)->dec_init_deps_left(this); 527 } 528 holder()->set_has_init_deps_processed(); 529 } 530 531 void TrainingData::init_dumptime_table(TRAPS) { 532 if (!need_data()) { 533 return; 534 } 535 _dumptime_training_data_dictionary = new GrowableArrayCHeap<DumpTimeTrainingDataInfo, mtClassShared>(); 536 if (CDSConfig::is_dumping_final_static_archive()) { 537 _archived_training_data_dictionary.iterate([&](TrainingData* record) { 538 _dumptime_training_data_dictionary->append(record); 539 }); 540 } else { 541 TrainingDataLocker l; 542 543 ResourceMark rm; 544 Visitor visitor(training_data_set()->size()); 545 training_data_set()->iterate_all([&](const TrainingData::Key* k, TrainingData* td) { 546 td->prepare(visitor); 547 if (!td->is_CompileTrainingData()) { 548 _dumptime_training_data_dictionary->append(td); 549 } 550 }); 551 552 if (VerifyTrainingData) { 553 training_data_set()->verify(); 554 } 555 } 556 557 prepare_recompilation_schedule(CHECK); 558 } 559 560 void TrainingData::prepare_recompilation_schedule(TRAPS) { 561 if (!need_data()) { 562 return; 563 } 564 auto nmethods = MethodProfiler::sampled_nmethods(); 565 GrowableArray<MethodTrainingData*> dyn_recompilation_schedule; 566 for (auto it = nmethods->begin(); it != nmethods->end(); ++it) { 567 nmethod* nm = *it; 568 if (RecordOnlyTopCompilations && nm->method_profiling_count() == 0) { 569 break; 570 } 571 if (nm->method() != nullptr) { 572 MethodTrainingData* mtd = nm->method()->training_data_or_null(); 573 if (mtd != nullptr) { 574 dyn_recompilation_schedule.append(mtd); 575 } 576 } 577 } 578 delete nmethods; 579 ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); 580 _recompilation_schedule_for_dumping = MetadataFactory::new_array<MethodTrainingData*>(loader_data, dyn_recompilation_schedule.length(), CHECK); 581 int i = 0; 582 for (auto it = dyn_recompilation_schedule.begin(); it != dyn_recompilation_schedule.end(); ++it) { 583 _recompilation_schedule_for_dumping->at_put(i++, *it); 584 } 585 } 586 587 #if INCLUDE_CDS 588 void TrainingData::iterate_roots(MetaspaceClosure* it) { 589 if (!need_data()) { 590 return; 591 } 592 assert(_dumptime_training_data_dictionary != nullptr, ""); 593 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) { 594 _dumptime_training_data_dictionary->at(i).metaspace_pointers_do(it); 595 } 596 it->push(&_recompilation_schedule_for_dumping); 597 } 598 599 void TrainingData::dump_training_data() { 600 if (!need_data()) { 601 return; 602 } 603 write_training_data_dictionary(&_archived_training_data_dictionary_for_dumping); 604 } 605 606 void TrainingData::cleanup_training_data() { 607 if (_dumptime_training_data_dictionary != nullptr) { 608 ResourceMark rm; 609 Visitor visitor(_dumptime_training_data_dictionary->length()); 610 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) { 611 TrainingData* td = _dumptime_training_data_dictionary->at(i).training_data(); 612 td->cleanup(visitor); 613 } 614 } 615 _recompilation_status = nullptr; 616 } 617 618 void KlassTrainingData::cleanup(Visitor& visitor) { 619 if (visitor.is_visited(this)) { 620 return; 621 } 622 visitor.visit(this); 623 if (holder() != nullptr) { 624 bool is_excluded = !holder()->is_loaded() || SystemDictionaryShared::check_for_exclusion(holder(), nullptr); 625 if (is_excluded) { 626 ResourceMark rm; 627 log_debug(cds)("Cleanup KTD %s", name()->as_klass_external_name()); 628 _holder = nullptr; // reset 629 } 630 } 631 for (int i = 0; i < _comp_deps.length(); i++) { 632 _comp_deps.at(i)->cleanup(visitor); 633 } 634 } 635 636 void MethodTrainingData::cleanup(Visitor& visitor) { 637 if (visitor.is_visited(this)) { 638 return; 639 } 640 visitor.visit(this); 641 if (has_holder()) { 642 if (SystemDictionaryShared::check_for_exclusion(holder()->method_holder(), nullptr)) { 643 log_debug(cds)("Cleanup MTD %s::%s", name()->as_klass_external_name(), signature()->as_utf8()); 644 if (_final_profile != nullptr && _final_profile->method() != _holder) { 645 // FIXME: MDO still points at the stale method; either completely drop the MDO or zero out the link 646 log_warning(cds)("Stale MDO for %s::%s", name()->as_klass_external_name(), signature()->as_utf8()); 647 } 648 _holder = nullptr; 649 } 650 } 651 for (int i = 0; i < CompLevel_count; i++) { 652 CompileTrainingData* ctd = _last_toplevel_compiles[i]; 653 if (ctd != nullptr) { 654 ctd->cleanup(visitor); 655 } 656 } 657 } 658 659 void KlassTrainingData::verify() { 660 for (int i = 0; i < comp_dep_count(); i++) { 661 CompileTrainingData* ctd = comp_dep(i); 662 if (!ctd->_init_deps.contains(this)) { 663 print_on(tty); tty->cr(); 664 ctd->print_on(tty); tty->cr(); 665 } 666 guarantee(ctd->_init_deps.contains(this), ""); 667 } 668 } 669 670 void MethodTrainingData::verify() { 671 iterate_all_compiles([](CompileTrainingData* ctd) { 672 ctd->verify(); 673 674 int init_deps_left1 = ctd->init_deps_left(); 675 int init_deps_left2 = ctd->compute_init_deps_left(); 676 677 if (init_deps_left1 != init_deps_left2) { 678 ctd->print_on(tty); tty->cr(); 679 } 680 guarantee(init_deps_left1 == init_deps_left2, "mismatch: %d %d %d", 681 init_deps_left1, init_deps_left2, ctd->init_deps_left()); 682 }); 683 } 684 685 void CompileTrainingData::verify() { 686 for (int i = 0; i < init_dep_count(); i++) { 687 KlassTrainingData* ktd = init_dep(i); 688 if (ktd->has_holder() && ktd->holder()->is_shared_unregistered_class()) { 689 LogStreamHandle(Warning, training) log; 690 if (log.is_enabled()) { 691 ResourceMark rm; 692 log.print("CTD "); print_value_on(&log); 693 log.print(" depends on unregistered class %s", ktd->holder()->name()->as_C_string()); 694 } 695 } 696 if (!ktd->_comp_deps.contains(this)) { 697 print_on(tty); tty->cr(); 698 ktd->print_on(tty); tty->cr(); 699 } 700 guarantee(ktd->_comp_deps.contains(this), ""); 701 } 702 } 703 704 void CompileTrainingData::cleanup(Visitor& visitor) { 705 if (visitor.is_visited(this)) { 706 return; 707 } 708 visitor.visit(this); 709 method()->cleanup(visitor); 710 } 711 712 void TrainingData::serialize_training_data(SerializeClosure* soc) { 713 if (soc->writing()) { 714 _archived_training_data_dictionary_for_dumping.serialize_header(soc); 715 soc->do_ptr(&_recompilation_schedule_for_dumping); 716 } else { 717 _archived_training_data_dictionary.serialize_header(soc); 718 soc->do_ptr(&_recompilation_schedule); 719 } 720 } 721 722 void TrainingData::print_archived_training_data_on(outputStream* st) { 723 st->print_cr("Archived TrainingData Dictionary"); 724 TrainingDataPrinter tdp(st); 725 TrainingDataLocker::initialize(); 726 _archived_training_data_dictionary.iterate(&tdp); 727 if (_recompilation_schedule != nullptr && _recompilation_schedule->length() > 0) { 728 st->print_cr("Archived TrainingData Recompilation Schedule"); 729 for (int i = 0; i < _recompilation_schedule->length(); i++) { 730 st->print("%4d: ", i); 731 MethodTrainingData* mtd = _recompilation_schedule->at(i); 732 if (mtd != nullptr) { 733 mtd->print_on(st); 734 } else { 735 st->print("nullptr"); 736 } 737 st->cr(); 738 } 739 } 740 } 741 742 void TrainingData::Key::metaspace_pointers_do(MetaspaceClosure *iter) { 743 iter->push(&_name1); 744 iter->push(&_name2); 745 iter->push((TrainingData**)&_holder); 746 } 747 748 void TrainingData::metaspace_pointers_do(MetaspaceClosure* iter) { 749 _key.metaspace_pointers_do(iter); 750 } 751 752 bool TrainingData::Key::can_compute_cds_hash(const Key* const& k) { 753 return (k->name1() == nullptr || MetaspaceObj::is_shared(k->name1())) && 754 (k->name2() == nullptr || MetaspaceObj::is_shared(k->name2())) && 755 (k->holder() == nullptr || MetaspaceObj::is_shared(k->holder())); 756 } 757 758 uint TrainingData::Key::cds_hash(const Key* const& k) { 759 uint hash = 0; 760 if (k->holder() != nullptr) { 761 hash += SystemDictionaryShared::hash_for_shared_dictionary((address)k->holder()); 762 } 763 if (k->name1() != nullptr) { 764 hash += SystemDictionaryShared::hash_for_shared_dictionary((address)k->name1()); 765 } 766 if (k->name2() != nullptr) { 767 hash += SystemDictionaryShared::hash_for_shared_dictionary((address)k->name2()); 768 } 769 return hash; 770 } 771 772 void TrainingData::write_training_data_dictionary(TrainingDataDictionary* dictionary) { 773 if (!need_data()) { 774 return; 775 } 776 assert(_dumptime_training_data_dictionary != nullptr, ""); 777 CompactHashtableStats stats; 778 dictionary->reset(); 779 CompactHashtableWriter writer(_dumptime_training_data_dictionary->length(), &stats); 780 for (int i = 0; i < _dumptime_training_data_dictionary->length(); i++) { 781 TrainingData* td = _dumptime_training_data_dictionary->at(i).training_data(); 782 #ifdef ASSERT 783 for (int j = i+1; j < _dumptime_training_data_dictionary->length(); j++) { 784 TrainingData* td1 = _dumptime_training_data_dictionary->at(j).training_data(); 785 assert(!TrainingData::Key::equals(td1, td->key(), -1), "conflict"); 786 } 787 #endif // ASSERT 788 td = ArchiveBuilder::current()->get_buffered_addr(td); 789 uint hash = TrainingData::Key::cds_hash(td->key()); 790 u4 delta = ArchiveBuilder::current()->buffer_to_offset_u4((address)td); 791 writer.add(hash, delta); 792 } 793 writer.dump(dictionary, "training data dictionary"); 794 } 795 796 size_t TrainingData::estimate_size_for_archive() { 797 if (_dumptime_training_data_dictionary != nullptr) { 798 return CompactHashtableWriter::estimate_size(_dumptime_training_data_dictionary->length()); 799 } else { 800 return 0; 801 } 802 } 803 804 TrainingData* TrainingData::lookup_archived_training_data(const Key* k) { 805 // For this to work, all components of the key must be in shared metaspace. 806 if (!TrainingData::Key::can_compute_cds_hash(k) || _archived_training_data_dictionary.empty()) { 807 return nullptr; 808 } 809 uint hash = TrainingData::Key::cds_hash(k); 810 TrainingData* td = _archived_training_data_dictionary.lookup(k, hash, -1 /*unused*/); 811 if (td != nullptr) { 812 if ((td->is_KlassTrainingData() && td->as_KlassTrainingData()->has_holder()) || 813 (td->is_MethodTrainingData() && td->as_MethodTrainingData()->has_holder())) { 814 return td; 815 } else { 816 // FIXME: decide what to do with symbolic TD 817 LogStreamHandle(Trace, training) log; 818 if (log.is_enabled()) { 819 ResourceMark rm; 820 log.print_cr("Ignored symbolic TrainingData:"); 821 log.print_cr(" Key: %s %s", 822 (k->name1() != nullptr ? k->name1()->as_C_string() : "(null)"), 823 (k->name2() != nullptr ? k->name2()->as_C_string() : "(null)")); 824 td->print_on(&log); 825 log.cr(); 826 } 827 } 828 } 829 return nullptr; 830 } 831 #endif 832 833 KlassTrainingData* TrainingData::lookup_for(InstanceKlass* ik) { 834 if (TrainingData::have_data() && ik != nullptr && ik->is_loaded()) { 835 TrainingData::Key key(ik); 836 TrainingData* td = TrainingData::lookup_archived_training_data(&key); 837 if (td != nullptr && td->is_KlassTrainingData()) { 838 return td->as_KlassTrainingData(); 839 } 840 } 841 return nullptr; 842 } 843 844 MethodTrainingData* TrainingData::lookup_for(Method* m) { 845 if (TrainingData::have_data() && m != nullptr) { 846 KlassTrainingData* holder_ktd = TrainingData::lookup_for(m->method_holder()); 847 if (holder_ktd != nullptr) { 848 TrainingData::Key key(m->name(), m->signature(), holder_ktd); 849 TrainingData* td = TrainingData::lookup_archived_training_data(&key); 850 if (td != nullptr && td->is_MethodTrainingData()) { 851 return td->as_MethodTrainingData(); 852 } 853 } 854 } 855 return nullptr; 856 } 857 858 template <typename T> 859 void TrainingData::DepList<T>::metaspace_pointers_do(MetaspaceClosure* iter) { 860 iter->push(&_deps); 861 } 862 863 void KlassTrainingData::metaspace_pointers_do(MetaspaceClosure* iter) { 864 log_trace(cds)("Iter(KlassTrainingData): %p", this); 865 TrainingData::metaspace_pointers_do(iter); 866 _comp_deps.metaspace_pointers_do(iter); 867 iter->push(&_holder); 868 } 869 870 void MethodTrainingData::metaspace_pointers_do(MetaspaceClosure* iter) { 871 log_trace(cds)("Iter(MethodTrainingData): %p", this); 872 TrainingData::metaspace_pointers_do(iter); 873 iter->push(&_klass); 874 iter->push((Method**)&_holder); 875 for (int i = 0; i < CompLevel_count; i++) { 876 iter->push(&_last_toplevel_compiles[i]); 877 } 878 iter->push(&_final_profile); 879 iter->push(&_final_counters); 880 } 881 882 void CompileTrainingData::metaspace_pointers_do(MetaspaceClosure* iter) { 883 log_trace(cds)("Iter(CompileTrainingData): %p", this); 884 TrainingData::metaspace_pointers_do(iter); 885 _init_deps.metaspace_pointers_do(iter); 886 _ci_records.metaspace_pointers_do(iter); 887 iter->push(&_method); 888 } 889 890 template <typename T> 891 void TrainingData::DepList<T>::prepare(ClassLoaderData* loader_data) { 892 if (_deps == nullptr && _deps_dyn != nullptr) { 893 int len = _deps_dyn->length(); 894 _deps = MetadataFactory::new_array_from_c_heap<T>(len, mtClassShared); 895 for (int i = 0; i < len; i++) { 896 _deps->at_put(i, _deps_dyn->at(i)); // copy 897 } 898 } 899 } 900 901 KlassTrainingData* KlassTrainingData::allocate(InstanceKlass* holder) { 902 assert(need_data() || have_data(), ""); 903 return new (mtClassShared) KlassTrainingData(holder); 904 } 905 906 MethodTrainingData* MethodTrainingData::allocate(KlassTrainingData* ktd, Method* m) { 907 assert(need_data() || have_data(), ""); 908 return new (mtClassShared) MethodTrainingData(ktd, m->name(), m->signature()); 909 } 910 911 CompileTrainingData* CompileTrainingData::allocate(MethodTrainingData* mtd, int level, int compile_id) { 912 assert(need_data() || have_data(), ""); 913 return new (mtClassShared) CompileTrainingData(mtd, level, compile_id); 914 } 915 916 void TrainingDataPrinter::do_value(TrainingData* td) { 917 #ifdef ASSERT 918 TrainingData::Key key(td->key()->name1(), td->key()->name2(), td->key()->holder()); 919 assert(td == TrainingData::archived_training_data_dictionary()->lookup(td->key(), TrainingData::Key::cds_hash(td->key()), -1), ""); 920 assert(td == TrainingData::archived_training_data_dictionary()->lookup(&key, TrainingData::Key::cds_hash(&key), -1), ""); 921 #endif // ASSERT 922 923 const char* type = (td->is_KlassTrainingData() ? "K" : 924 td->is_MethodTrainingData() ? "M" : 925 td->is_CompileTrainingData() ? "C" : "?"); 926 _st->print("%4d: %p %s ", _index++, td, type); 927 td->print_on(_st); 928 _st->cr(); 929 if (td->is_KlassTrainingData()) { 930 td->as_KlassTrainingData()->iterate_all_comp_deps([&](CompileTrainingData* ctd) { 931 ResourceMark rm; 932 _st->print_raw(" C "); 933 ctd->print_on(_st); 934 _st->cr(); 935 }); 936 } else if (td->is_MethodTrainingData()) { 937 td->as_MethodTrainingData()->iterate_all_compiles([&](CompileTrainingData* ctd) { 938 ResourceMark rm; 939 _st->print_raw(" C "); 940 ctd->print_on(_st); 941 _st->cr(); 942 }); 943 } else if (td->is_CompileTrainingData()) { 944 // ? 945 } 946 } 947 948 949 #if INCLUDE_CDS 950 void KlassTrainingData::remove_unshareable_info() { 951 TrainingData::remove_unshareable_info(); 952 _holder_mirror = nullptr; 953 _comp_deps.remove_unshareable_info(); 954 } 955 956 void MethodTrainingData::remove_unshareable_info() { 957 TrainingData::remove_unshareable_info(); 958 if (_final_counters != nullptr) { 959 _final_counters->remove_unshareable_info(); 960 } 961 if (_final_profile != nullptr) { 962 _final_profile->remove_unshareable_info(); 963 } 964 } 965 966 void CompileTrainingData::remove_unshareable_info() { 967 TrainingData::remove_unshareable_info(); 968 _init_deps.remove_unshareable_info(); 969 _ci_records.remove_unshareable_info(); 970 _init_deps_left = compute_init_deps_left(true); 971 } 972 973 #endif // INCLUDE_CDS