230 // By convention, the compiling thread is responsible for |
229 // By convention, the compiling thread is responsible for |
231 // recycling a non-blocking CompileTask. |
230 // recycling a non-blocking CompileTask. |
232 CompileTask::free(task); |
231 CompileTask::free(task); |
233 } |
232 } |
234 } |
233 } |
235 |
|
236 |
|
237 CompileTask* CompileTask::_task_free_list = NULL; |
|
238 #ifdef ASSERT |
|
239 int CompileTask::_num_allocated_tasks = 0; |
|
240 #endif |
|
241 /** |
|
242 * Allocate a CompileTask, from the free list if possible. |
|
243 */ |
|
244 CompileTask* CompileTask::allocate() { |
|
245 MutexLocker locker(CompileTaskAlloc_lock); |
|
246 CompileTask* task = NULL; |
|
247 |
|
248 if (_task_free_list != NULL) { |
|
249 task = _task_free_list; |
|
250 _task_free_list = task->next(); |
|
251 task->set_next(NULL); |
|
252 } else { |
|
253 task = new CompileTask(); |
|
254 DEBUG_ONLY(_num_allocated_tasks++;) |
|
255 assert (WhiteBoxAPI || _num_allocated_tasks < 10000, "Leaking compilation tasks?"); |
|
256 task->set_next(NULL); |
|
257 task->set_is_free(true); |
|
258 } |
|
259 assert(task->is_free(), "Task must be free."); |
|
260 task->set_is_free(false); |
|
261 return task; |
|
262 } |
|
263 |
|
264 |
|
265 /** |
|
266 * Add a task to the free list. |
|
267 */ |
|
268 void CompileTask::free(CompileTask* task) { |
|
269 MutexLocker locker(CompileTaskAlloc_lock); |
|
270 if (!task->is_free()) { |
|
271 task->set_code(NULL); |
|
272 assert(!task->lock()->is_locked(), "Should not be locked when freed"); |
|
273 JNIHandles::destroy_global(task->_method_holder); |
|
274 JNIHandles::destroy_global(task->_hot_method_holder); |
|
275 |
|
276 task->set_is_free(true); |
|
277 task->set_next(_task_free_list); |
|
278 _task_free_list = task; |
|
279 } |
|
280 } |
|
281 |
|
282 void CompileTask::initialize(int compile_id, |
|
283 methodHandle method, |
|
284 int osr_bci, |
|
285 int comp_level, |
|
286 methodHandle hot_method, |
|
287 int hot_count, |
|
288 const char* comment, |
|
289 bool is_blocking) { |
|
290 assert(!_lock->is_locked(), "bad locking"); |
|
291 |
|
292 _compile_id = compile_id; |
|
293 _method = method(); |
|
294 _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder()); |
|
295 _osr_bci = osr_bci; |
|
296 _is_blocking = is_blocking; |
|
297 _comp_level = comp_level; |
|
298 _num_inlined_bytecodes = 0; |
|
299 |
|
300 _is_complete = false; |
|
301 _is_success = false; |
|
302 _code_handle = NULL; |
|
303 |
|
304 _hot_method = NULL; |
|
305 _hot_method_holder = NULL; |
|
306 _hot_count = hot_count; |
|
307 _time_queued = 0; // tidy |
|
308 _comment = comment; |
|
309 _failure_reason = NULL; |
|
310 |
|
311 if (LogCompilation) { |
|
312 _time_queued = os::elapsed_counter(); |
|
313 if (hot_method.not_null()) { |
|
314 if (hot_method == method) { |
|
315 _hot_method = _method; |
|
316 } else { |
|
317 _hot_method = hot_method(); |
|
318 // only add loader or mirror if different from _method_holder |
|
319 _hot_method_holder = JNIHandles::make_global(hot_method->method_holder()->klass_holder()); |
|
320 } |
|
321 } |
|
322 } |
|
323 |
|
324 _next = NULL; |
|
325 } |
|
326 |
|
327 // ------------------------------------------------------------------ |
|
328 // CompileTask::code/set_code |
|
329 nmethod* CompileTask::code() const { |
|
330 if (_code_handle == NULL) return NULL; |
|
331 return _code_handle->code(); |
|
332 } |
|
333 void CompileTask::set_code(nmethod* nm) { |
|
334 if (_code_handle == NULL && nm == NULL) return; |
|
335 guarantee(_code_handle != NULL, ""); |
|
336 _code_handle->set_code(nm); |
|
337 if (nm == NULL) _code_handle = NULL; // drop the handle also |
|
338 } |
|
339 |
|
340 void CompileTask::mark_on_stack() { |
|
341 // Mark these methods as something redefine classes cannot remove. |
|
342 _method->set_on_stack(true); |
|
343 if (_hot_method != NULL) { |
|
344 _hot_method->set_on_stack(true); |
|
345 } |
|
346 } |
|
347 |
|
348 // RedefineClasses support |
|
349 void CompileTask::metadata_do(void f(Metadata*)) { |
|
350 f(method()); |
|
351 if (hot_method() != NULL && hot_method() != method()) { |
|
352 f(hot_method()); |
|
353 } |
|
354 } |
|
355 |
|
356 // ------------------------------------------------------------------ |
|
357 // CompileTask::print_line_on_error |
|
358 // |
|
359 // This function is called by fatal error handler when the thread |
|
360 // causing troubles is a compiler thread. |
|
361 // |
|
362 // Do not grab any lock, do not allocate memory. |
|
363 // |
|
364 // Otherwise it's the same as CompileTask::print_line() |
|
365 // |
|
366 void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) { |
|
367 // print compiler name |
|
368 st->print("%s:", CompileBroker::compiler_name(comp_level())); |
|
369 print_compilation(st); |
|
370 } |
|
371 |
|
372 // ------------------------------------------------------------------ |
|
373 // CompileTask::print_line |
|
374 void CompileTask::print_tty() { |
|
375 ttyLocker ttyl; // keep the following output all in one block |
|
376 // print compiler name if requested |
|
377 if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level())); |
|
378 print_compilation(tty); |
|
379 } |
|
380 |
|
381 // ------------------------------------------------------------------ |
|
382 // CompileTask::print_compilation_impl |
|
383 void CompileTask::print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level, |
|
384 bool is_osr_method, int osr_bci, bool is_blocking, |
|
385 const char* msg, bool short_form, bool cr) { |
|
386 if (!short_form) { |
|
387 st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp |
|
388 } |
|
389 st->print("%4d ", compile_id); // print compilation number |
|
390 |
|
391 // For unloaded methods the transition to zombie occurs after the |
|
392 // method is cleared so it's impossible to report accurate |
|
393 // information for that case. |
|
394 bool is_synchronized = false; |
|
395 bool has_exception_handler = false; |
|
396 bool is_native = false; |
|
397 if (method != NULL) { |
|
398 is_synchronized = method->is_synchronized(); |
|
399 has_exception_handler = method->has_exception_handler(); |
|
400 is_native = method->is_native(); |
|
401 } |
|
402 // method attributes |
|
403 const char compile_type = is_osr_method ? '%' : ' '; |
|
404 const char sync_char = is_synchronized ? 's' : ' '; |
|
405 const char exception_char = has_exception_handler ? '!' : ' '; |
|
406 const char blocking_char = is_blocking ? 'b' : ' '; |
|
407 const char native_char = is_native ? 'n' : ' '; |
|
408 |
|
409 // print method attributes |
|
410 st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char); |
|
411 |
|
412 if (TieredCompilation) { |
|
413 if (comp_level != -1) st->print("%d ", comp_level); |
|
414 else st->print("- "); |
|
415 } |
|
416 st->print(" "); // more indent |
|
417 |
|
418 if (method == NULL) { |
|
419 st->print("(method)"); |
|
420 } else { |
|
421 method->print_short_name(st); |
|
422 if (is_osr_method) { |
|
423 st->print(" @ %d", osr_bci); |
|
424 } |
|
425 if (method->is_native()) |
|
426 st->print(" (native)"); |
|
427 else |
|
428 st->print(" (%d bytes)", method->code_size()); |
|
429 } |
|
430 |
|
431 if (msg != NULL) { |
|
432 st->print(" %s", msg); |
|
433 } |
|
434 if (cr) { |
|
435 st->cr(); |
|
436 } |
|
437 } |
|
438 |
|
439 // ------------------------------------------------------------------ |
|
440 // CompileTask::print_inlining |
|
441 void CompileTask::print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) { |
|
442 // 1234567 |
|
443 st->print(" "); // print timestamp |
|
444 // 1234 |
|
445 st->print(" "); // print compilation number |
|
446 |
|
447 // method attributes |
|
448 if (method->is_loaded()) { |
|
449 const char sync_char = method->is_synchronized() ? 's' : ' '; |
|
450 const char exception_char = method->has_exception_handlers() ? '!' : ' '; |
|
451 const char monitors_char = method->has_monitor_bytecodes() ? 'm' : ' '; |
|
452 |
|
453 // print method attributes |
|
454 st->print(" %c%c%c ", sync_char, exception_char, monitors_char); |
|
455 } else { |
|
456 // %s!bn |
|
457 st->print(" "); // print method attributes |
|
458 } |
|
459 |
|
460 if (TieredCompilation) { |
|
461 st->print(" "); |
|
462 } |
|
463 st->print(" "); // more indent |
|
464 st->print(" "); // initial inlining indent |
|
465 |
|
466 for (int i = 0; i < inline_level; i++) st->print(" "); |
|
467 |
|
468 st->print("@ %d ", bci); // print bci |
|
469 method->print_short_name(st); |
|
470 if (method->is_loaded()) |
|
471 st->print(" (%d bytes)", method->code_size()); |
|
472 else |
|
473 st->print(" (not loaded)"); |
|
474 |
|
475 if (msg != NULL) { |
|
476 st->print(" %s", msg); |
|
477 } |
|
478 st->cr(); |
|
479 } |
|
480 |
|
481 // ------------------------------------------------------------------ |
|
482 // CompileTask::print_inline_indent |
|
483 void CompileTask::print_inline_indent(int inline_level, outputStream* st) { |
|
484 // 1234567 |
|
485 st->print(" "); // print timestamp |
|
486 // 1234 |
|
487 st->print(" "); // print compilation number |
|
488 // %s!bn |
|
489 st->print(" "); // print method attributes |
|
490 if (TieredCompilation) { |
|
491 st->print(" "); |
|
492 } |
|
493 st->print(" "); // more indent |
|
494 st->print(" "); // initial inlining indent |
|
495 for (int i = 0; i < inline_level; i++) st->print(" "); |
|
496 } |
|
497 |
|
498 // ------------------------------------------------------------------ |
|
499 // CompileTask::print_compilation |
|
500 void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form, bool cr) { |
|
501 bool is_osr_method = osr_bci() != InvocationEntryBci; |
|
502 print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr); |
|
503 } |
|
504 |
|
505 // ------------------------------------------------------------------ |
|
506 // CompileTask::log_task |
|
507 void CompileTask::log_task(xmlStream* log) { |
|
508 Thread* thread = Thread::current(); |
|
509 methodHandle method(thread, this->method()); |
|
510 ResourceMark rm(thread); |
|
511 |
|
512 // <task compiler='Cx' id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'> |
|
513 log->print(" compiler='%s' compile_id='%d'", _comp_level <= CompLevel_full_profile ? "C1" : "C2", _compile_id); |
|
514 if (_osr_bci != CompileBroker::standard_entry_bci) { |
|
515 log->print(" compile_kind='osr'"); // same as nmethod::compile_kind |
|
516 } // else compile_kind='c2c' |
|
517 if (!method.is_null()) log->method(method); |
|
518 if (_osr_bci != CompileBroker::standard_entry_bci) { |
|
519 log->print(" osr_bci='%d'", _osr_bci); |
|
520 } |
|
521 if (_comp_level != CompLevel_highest_tier) { |
|
522 log->print(" level='%d'", _comp_level); |
|
523 } |
|
524 if (_is_blocking) { |
|
525 log->print(" blocking='1'"); |
|
526 } |
|
527 log->stamp(); |
|
528 } |
|
529 |
|
530 |
|
531 // ------------------------------------------------------------------ |
|
532 // CompileTask::log_task_queued |
|
533 void CompileTask::log_task_queued() { |
|
534 Thread* thread = Thread::current(); |
|
535 ttyLocker ttyl; |
|
536 ResourceMark rm(thread); |
|
537 |
|
538 xtty->begin_elem("task_queued"); |
|
539 log_task(xtty); |
|
540 if (_comment != NULL) { |
|
541 xtty->print(" comment='%s'", _comment); |
|
542 } |
|
543 if (_hot_method != NULL) { |
|
544 methodHandle hot(thread, _hot_method); |
|
545 methodHandle method(thread, _method); |
|
546 if (hot() != method()) { |
|
547 xtty->method(hot); |
|
548 } |
|
549 } |
|
550 if (_hot_count != 0) { |
|
551 xtty->print(" hot_count='%d'", _hot_count); |
|
552 } |
|
553 xtty->end_elem(); |
|
554 } |
|
555 |
|
556 |
|
557 // ------------------------------------------------------------------ |
|
558 // CompileTask::log_task_start |
|
559 void CompileTask::log_task_start(CompileLog* log) { |
|
560 log->begin_head("task"); |
|
561 log_task(log); |
|
562 log->end_head(); |
|
563 } |
|
564 |
|
565 |
|
566 // ------------------------------------------------------------------ |
|
567 // CompileTask::log_task_done |
|
568 void CompileTask::log_task_done(CompileLog* log) { |
|
569 Thread* thread = Thread::current(); |
|
570 methodHandle method(thread, this->method()); |
|
571 ResourceMark rm(thread); |
|
572 |
|
573 if (!_is_success) { |
|
574 const char* reason = _failure_reason != NULL ? _failure_reason : "unknown"; |
|
575 log->elem("failure reason='%s'", reason); |
|
576 } |
|
577 |
|
578 // <task_done ... stamp='1.234'> </task> |
|
579 nmethod* nm = code(); |
|
580 log->begin_elem("task_done success='%d' nmsize='%d' count='%d'", |
|
581 _is_success, nm == NULL ? 0 : nm->content_size(), |
|
582 method->invocation_count()); |
|
583 int bec = method->backedge_count(); |
|
584 if (bec != 0) log->print(" backedge_count='%d'", bec); |
|
585 // Note: "_is_complete" is about to be set, but is not. |
|
586 if (_num_inlined_bytecodes != 0) { |
|
587 log->print(" inlined_bytes='%d'", _num_inlined_bytecodes); |
|
588 } |
|
589 log->stamp(); |
|
590 log->end_elem(); |
|
591 log->tail("task"); |
|
592 log->clear_identities(); // next task will have different CI |
|
593 if (log->unflushed_count() > 2000) { |
|
594 log->flush(); |
|
595 } |
|
596 log->mark_file_end(); |
|
597 } |
|
598 |
|
599 |
|
600 |
234 |
601 /** |
235 /** |
602 * Add a CompileTask to a CompileQueue. |
236 * Add a CompileTask to a CompileQueue. |
603 */ |
237 */ |
604 void CompileQueue::add(CompileTask* task) { |
238 void CompileQueue::add(CompileTask* task) { |