1 /* 2 * Copyright (c) 1998, 2025, 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 "compiler/compilationPolicy.hpp" 26 #include "compiler/compileBroker.hpp" 27 #include "compiler/compileLog.hpp" 28 #include "compiler/compilerDirectives.hpp" 29 #include "compiler/compileTask.hpp" 30 #include "logging/log.hpp" 31 #include "logging/logStream.hpp" 32 #include "memory/resourceArea.hpp" 33 #include "oops/klass.inline.hpp" 34 #include "oops/method.inline.hpp" 35 #include "runtime/handles.inline.hpp" 36 #include "runtime/jniHandles.hpp" 37 #include "runtime/mutexLocker.hpp" 38 39 int CompileTask::_active_tasks = 0; 40 41 CompileTask::CompileTask(int compile_id, 42 const methodHandle& method, 43 int osr_bci, 44 int comp_level, 45 int hot_count, 46 AOTCodeEntry* aot_code_entry, 47 CompileTask::CompileReason compile_reason, 48 CompileQueue* compile_queue, 49 bool requires_online_compilation, 50 bool is_blocking) { 51 Thread* thread = Thread::current(); 52 _compile_id = compile_id; 53 _method = method(); 54 _method_holder = JNIHandles::make_weak_global(Handle(thread, method->method_holder()->klass_holder())); 55 _osr_bci = osr_bci; 56 _requires_online_compilation = requires_online_compilation; 57 _is_blocking = is_blocking; 58 _comp_level = comp_level; 59 _num_inlined_bytecodes = 0; 60 61 _waiting_count = 0; 62 63 _is_complete = false; 64 _is_success = false; 65 66 _next = nullptr; 67 _prev = nullptr; 68 69 _hot_count = hot_count; 70 _time_created = os::elapsed_counter(); 71 _time_queued = 0; 72 _time_started = 0; 73 _time_finished = 0; 74 _aot_load_start = 0; 75 _aot_load_finish = 0; 76 _compile_reason = compile_reason; 77 _nm_content_size = 0; 78 _nm_insts_size = 0; 79 _nm_total_size = 0; 80 _failure_reason = nullptr; 81 _failure_reason_on_C_heap = false; 82 _training_data = nullptr; 83 _aot_code_entry = aot_code_entry; 84 _compile_queue = compile_queue; 85 86 AbstractCompiler* comp = CompileBroker::compiler(comp_level); 87 #if INCLUDE_JVMCI 88 if (comp->is_jvmci() && CompileBroker::compiler3() != nullptr) { 89 assert(_method != nullptr, "sanity"); 90 if (((JVMCICompiler*)comp)->force_comp_at_level_simple(method)) { 91 comp = CompileBroker::compiler3(); 92 } 93 } 94 #endif 95 _compiler = comp; 96 _directive = DirectivesStack::getMatchingDirective(method, comp); 97 98 JVMCI_ONLY(_has_waiter = comp->is_jvmci();) 99 JVMCI_ONLY(_blocking_jvmci_compile_state = nullptr;) 100 _arena_bytes = 0; 101 102 _next = nullptr; 103 104 Atomic::add(&_active_tasks, 1); 105 } 106 107 CompileTask::~CompileTask() { 108 if ((_method_holder != nullptr && JNIHandles::is_weak_global_handle(_method_holder))) { 109 JNIHandles::destroy_weak_global(_method_holder); 110 } else { 111 JNIHandles::destroy_global(_method_holder); 112 } 113 if (_failure_reason_on_C_heap && _failure_reason != nullptr) { 114 os::free((void*) _failure_reason); 115 _failure_reason = nullptr; 116 _failure_reason_on_C_heap = false; 117 } 118 119 if (Atomic::sub(&_active_tasks, 1) == 0) { 120 MonitorLocker wait_ml(CompileTaskWait_lock); 121 wait_ml.notify_all(); 122 } 123 } 124 125 void CompileTask::wait_for_no_active_tasks() { 126 MonitorLocker locker(CompileTaskWait_lock); 127 while (Atomic::load(&_active_tasks) > 0) { 128 locker.wait(); 129 } 130 } 131 132 /** 133 * Returns the compiler for this task. 134 */ 135 AbstractCompiler* CompileTask::compiler() const { 136 assert(_compiler != nullptr, "should be set"); 137 return _compiler; 138 } 139 140 // Replace weak handles by strong handles to avoid unloading during compilation. 141 CompileTask* CompileTask::select_for_compilation() { 142 if (_compile_reason == Reason_Preload) { 143 return this; 144 } 145 if (is_unloaded()) { 146 // Guard against concurrent class unloading 147 return nullptr; 148 } 149 Thread* thread = Thread::current(); 150 assert(_method->method_holder()->is_loader_alive(), "should be alive"); 151 Handle method_holder(thread, _method->method_holder()->klass_holder()); 152 JNIHandles::destroy_weak_global(_method_holder); 153 _method_holder = JNIHandles::make_global(method_holder); 154 return this; 155 } 156 157 void CompileTask::mark_on_stack() { 158 if (is_unloaded()) { 159 return; 160 } 161 // Mark these methods as something redefine classes cannot remove. 162 _method->set_on_stack(true); 163 } 164 165 bool CompileTask::is_unloaded() const { 166 if (preload()) return false; 167 return _method_holder != nullptr && JNIHandles::is_weak_global_handle(_method_holder) && JNIHandles::is_weak_global_cleared(_method_holder); 168 } 169 170 // RedefineClasses support 171 void CompileTask::metadata_do(MetadataClosure* f) { 172 if (is_unloaded()) { 173 return; 174 } 175 f->do_metadata(method()); 176 } 177 178 // ------------------------------------------------------------------ 179 // CompileTask::print_line_on_error 180 // 181 // This function is called by fatal error handler when the thread 182 // causing troubles is a compiler thread. 183 // 184 // Do not grab any lock, do not allocate memory. 185 // 186 // Otherwise it's the same as CompileTask::print_line() 187 // 188 void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) { 189 // print compiler name 190 st->print("%s:", compiler()->name()); 191 print(st); 192 } 193 194 // ------------------------------------------------------------------ 195 // CompileTask::print_tty 196 void CompileTask::print_tty() { 197 ttyLocker ttyl; // keep the following output all in one block 198 print(tty); 199 } 200 201 // ------------------------------------------------------------------ 202 // CompileTask::print_impl 203 void CompileTask::print_impl(outputStream* st, Method* method, int compile_id, int comp_level, 204 bool is_osr_method, int osr_bci, bool is_blocking, bool is_aot, bool is_preload, 205 const char* compiler_name, 206 const char* msg, bool short_form, bool cr, 207 jlong time_created, jlong time_queued, jlong time_started, jlong time_finished, 208 jlong aot_load_start, jlong aot_load_finish) { 209 if (!short_form) { 210 { 211 stringStream ss; 212 ss.print(UINT64_FORMAT, (uint64_t) tty->time_stamp().milliseconds()); 213 st->print("%7s ", ss.freeze()); 214 } 215 { // Time waiting to be put on queue 216 stringStream ss; 217 if (time_created != 0 && time_queued != 0) { 218 ss.print("W%.1f", TimeHelper::counter_to_millis(time_queued - time_created)); 219 } 220 st->print("%7s ", ss.freeze()); 221 } 222 { // Time in queue 223 stringStream ss; 224 if (time_queued != 0 && time_started != 0) { 225 ss.print("Q%.1f", TimeHelper::counter_to_millis(time_started - time_queued)); 226 } 227 st->print("%7s ", ss.freeze()); 228 } 229 { // Time in compilation 230 stringStream ss; 231 if (time_started != 0 && time_finished != 0) { 232 ss.print("C%.1f", TimeHelper::counter_to_millis(time_finished - time_started)); 233 } 234 st->print("%7s ", ss.freeze()); 235 } 236 { // Time to load from AOT code cache 237 stringStream ss; 238 if (aot_load_start != 0 && aot_load_finish != 0) { 239 ss.print("A%.1f", TimeHelper::counter_to_millis(aot_load_finish - aot_load_start)); 240 } 241 st->print("%7s ", ss.freeze()); 242 } 243 st->print(" "); 244 } 245 246 // print compiler name if requested 247 if (CIPrintCompilerName) { 248 st->print("%s:", compiler_name); 249 } 250 st->print("%4d ", compile_id); // print compilation number 251 252 bool is_synchronized = false; 253 bool has_exception_handler = false; 254 bool is_native = false; 255 if (method != nullptr) { 256 is_synchronized = method->is_synchronized(); 257 has_exception_handler = method->has_exception_handler(); 258 is_native = method->is_native(); 259 } 260 // method attributes 261 const char compile_type = is_osr_method ? '%' : ' '; 262 const char sync_char = is_synchronized ? 's' : ' '; 263 const char exception_char = has_exception_handler ? '!' : ' '; 264 const char blocking_char = is_blocking ? 'b' : ' '; 265 const char native_char = is_native ? 'n' : ' '; 266 const char aot_char = is_aot ? 'A' : ' '; 267 const char preload_char = is_preload ? 'P' : ' '; 268 269 // print method attributes 270 st->print("%c%c%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char, aot_char, preload_char); 271 272 if (TieredCompilation) { 273 if (comp_level != -1) st->print("%d ", comp_level); 274 else st->print("- "); 275 } 276 st->print(" "); // more indent 277 278 if (method == nullptr) { 279 st->print("(method)"); 280 } else { 281 method->print_short_name(st); 282 if (is_osr_method) { 283 st->print(" @ %d", osr_bci); 284 } 285 if (method->is_native()) 286 st->print(" (native)"); 287 else 288 st->print(" (%d bytes)", method->code_size()); 289 } 290 291 if (msg != nullptr) { 292 st->print(" %s", msg); 293 } 294 if (cr) { 295 st->cr(); 296 } 297 } 298 299 // ------------------------------------------------------------------ 300 // CompileTask::print_compilation 301 void CompileTask::print(outputStream* st, const char* msg, bool short_form, bool cr) { 302 bool is_osr_method = osr_bci() != InvocationEntryBci; 303 print_impl(st, is_unloaded() ? nullptr : method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), is_aot(), preload(), 304 compiler()->name(), msg, short_form, cr, _time_created, _time_queued, _time_started, _time_finished, _aot_load_start, _aot_load_finish); 305 } 306 307 // ------------------------------------------------------------------ 308 // CompileTask::log_task 309 void CompileTask::log_task(xmlStream* log) { 310 Thread* thread = Thread::current(); 311 methodHandle method(thread, this->method()); 312 ResourceMark rm(thread); 313 314 // <task id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'> 315 log->print(" compile_id='%d'", _compile_id); 316 if (_osr_bci != CompileBroker::standard_entry_bci) { 317 log->print(" compile_kind='osr'"); // same as nmethod::compile_kind 318 } // else compile_kind='c2c' 319 if (!method.is_null()) log->method(method()); 320 if (_osr_bci != CompileBroker::standard_entry_bci) { 321 log->print(" osr_bci='%d'", _osr_bci); 322 } 323 if (_comp_level != CompilationPolicy::highest_compile_level()) { 324 log->print(" level='%d'", _comp_level); 325 } 326 if (_is_blocking) { 327 log->print(" blocking='1'"); 328 } 329 } 330 331 // ------------------------------------------------------------------ 332 // CompileTask::log_task_queued 333 void CompileTask::log_task_queued() { 334 ttyLocker ttyl; 335 ResourceMark rm; 336 NoSafepointVerifier nsv; 337 338 xtty->begin_elem("task_queued"); 339 log_task(xtty); 340 assert(_compile_reason > CompileTask::Reason_None && _compile_reason < CompileTask::Reason_Count, "Valid values"); 341 xtty->print(" comment='%s'", reason_name(_compile_reason)); 342 343 if (_hot_count != 0) { 344 xtty->print(" hot_count='%d'", _hot_count); 345 } 346 xtty->stamp(); 347 xtty->end_elem(); 348 } 349 350 351 // ------------------------------------------------------------------ 352 // CompileTask::log_task_start 353 void CompileTask::log_task_start(CompileLog* log) { 354 log->begin_head("task"); 355 log_task(log); 356 log->stamp(); 357 log->end_head(); 358 } 359 360 361 // ------------------------------------------------------------------ 362 // CompileTask::log_task_done 363 void CompileTask::log_task_done(CompileLog* log) { 364 Thread* thread = Thread::current(); 365 methodHandle method(thread, this->method()); 366 ResourceMark rm(thread); 367 368 if (!_is_success) { 369 assert(_failure_reason != nullptr, "missing"); 370 const char* reason = _failure_reason != nullptr ? _failure_reason : "unknown"; 371 log->begin_elem("failure reason='"); 372 log->text("%s", reason); 373 log->print("'"); 374 log->end_elem(); 375 } 376 377 // <task_done ... stamp='1.234'> </task> 378 log->begin_elem("task_done success='%d' nmsize='%d' count='%d'", 379 _is_success, _nm_content_size, 380 method->invocation_count()); 381 int bec = method->backedge_count(); 382 if (bec != 0) log->print(" backedge_count='%d'", bec); 383 // Note: "_is_complete" is about to be set, but is not. 384 if (_num_inlined_bytecodes != 0) { 385 log->print(" inlined_bytes='%d'", _num_inlined_bytecodes); 386 } 387 log->stamp(); 388 log->end_elem(); 389 log->clear_identities(); // next task will have different CI 390 log->tail("task"); 391 log->flush(); 392 log->mark_file_end(); 393 } 394 395 // ------------------------------------------------------------------ 396 // CompileTask::check_break_at_flags 397 bool CompileTask::check_break_at_flags() { 398 int compile_id = this->_compile_id; 399 bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci); 400 401 if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) { 402 return true; 403 } else { 404 return (compile_id == CIBreakAt); 405 } 406 } 407 408 // ------------------------------------------------------------------ 409 // CompileTask::print_inlining 410 void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, InliningResult result, const char* msg) { 411 print_inlining_header(st, method, inline_level, bci); 412 print_inlining_inner_message(st, result, msg); 413 st->cr(); 414 } 415 416 void CompileTask::print_inlining_header(outputStream* st, ciMethod* method, int inline_level, int bci) { 417 // 1234567 418 st->print(" "); // print timestamp 419 // 1234 420 st->print(" "); // print compilation number 421 422 // method attributes 423 if (method->is_loaded()) { 424 const char sync_char = method->is_synchronized() ? 's' : ' '; 425 const char exception_char = method->has_exception_handlers() ? '!' : ' '; 426 const char monitors_char = method->has_monitor_bytecodes() ? 'm' : ' '; 427 428 // print method attributes 429 st->print(" %c%c%c ", sync_char, exception_char, monitors_char); 430 } else { 431 // %s!bn 432 st->print(" "); // print method attributes 433 } 434 435 if (TieredCompilation) { 436 st->print(" "); 437 } 438 st->print(" "); // more indent 439 st->print(" "); // initial inlining indent 440 441 for (int i = 0; i < inline_level; i++) { 442 st->print(" "); 443 } 444 445 st->print("@ %d ", bci); // print bci 446 print_inline_inner_method_info(st, method); 447 } 448 449 void CompileTask::print_inline_inner_method_info(outputStream* st, ciMethod* method) { 450 method->print_short_name(st); 451 if (method->is_loaded()) { 452 st->print(" (%d bytes)", method->code_size()); 453 } else { 454 st->print(" (not loaded)"); 455 } 456 } 457 458 void CompileTask::print_inline_indent(int inline_level, outputStream* st) { 459 // 1234567 460 st->print(" "); // print timestamp 461 // 1234 462 st->print(" "); // print compilation number 463 // %s!bn 464 st->print(" "); // print method attributes 465 if (TieredCompilation) { 466 st->print(" "); 467 } 468 st->print(" "); // more indent 469 st->print(" "); // initial inlining indent 470 for (int i = 0; i < inline_level; i++) { 471 st->print(" "); 472 } 473 } 474 475 void CompileTask::print_inlining_inner_message(outputStream* st, InliningResult result, const char* msg) { 476 if (msg != nullptr) { 477 st->print(" %s%s", result == InliningResult::SUCCESS ? "" : "failed to inline: ", msg); 478 } else if (result == InliningResult::FAILURE) { 479 st->print(" %s", "failed to inline"); 480 } 481 } 482 483 void CompileTask::print_ul(const char* msg){ 484 LogTarget(Info, jit, compilation) lt; 485 if (lt.is_enabled()) { 486 LogStream ls(lt); 487 print(&ls, msg, /* short form */ true, /* cr */ true); 488 } 489 } 490 491 void CompileTask::print_ul(const nmethod* nm, const char* msg) { 492 LogTarget(Info, jit, compilation) lt; 493 if (lt.is_enabled()) { 494 LogStream ls(lt); 495 print_impl(&ls, nm->method(), nm->compile_id(), 496 nm->comp_level(), nm->is_osr_method(), 497 nm->is_osr_method() ? nm->osr_entry_bci() : -1, 498 /*is_blocking*/ false, nm->aot_code_entry() != nullptr, 499 nm->preloaded(), nm->compiler_name(), 500 msg, /* short form */ true, /* cr */ true); 501 } 502 } 503 504 void CompileTask::print_inlining_ul(ciMethod* method, int inline_level, int bci, InliningResult result, const char* msg) { 505 LogTarget(Debug, jit, inlining) lt; 506 if (lt.is_enabled()) { 507 LogStream ls(lt); 508 print_inlining_inner(&ls, method, inline_level, bci, result, msg); 509 } 510 } 511