Mercurial > hg > graal-jvmci-8
comparison src/share/vm/code/nmethod.cpp @ 12324:510fbd28919c
8020151: PSR:PERF Large performance regressions when code cache is filled
Summary: Code cache sweeping based on method hotness; removed speculatively disconnect
Reviewed-by: kvn, iveresov
author | anoll |
---|---|
date | Fri, 27 Sep 2013 10:50:55 +0200 |
parents | 3bfb204913de |
children | 268e7a2178d7 |
comparison
equal
deleted
inserted
replaced
12323:c9ccd7b85f20 | 12324:510fbd28919c |
---|---|
460 // Fill in default values for various flag fields | 460 // Fill in default values for various flag fields |
461 void nmethod::init_defaults() { | 461 void nmethod::init_defaults() { |
462 _state = alive; | 462 _state = alive; |
463 _marked_for_reclamation = 0; | 463 _marked_for_reclamation = 0; |
464 _has_flushed_dependencies = 0; | 464 _has_flushed_dependencies = 0; |
465 _speculatively_disconnected = 0; | |
466 _has_unsafe_access = 0; | 465 _has_unsafe_access = 0; |
467 _has_method_handle_invokes = 0; | 466 _has_method_handle_invokes = 0; |
468 _lazy_critical_native = 0; | 467 _lazy_critical_native = 0; |
469 _has_wide_vectors = 0; | 468 _has_wide_vectors = 0; |
470 _marked_for_deoptimization = 0; | 469 _marked_for_deoptimization = 0; |
479 _oops_do_mark_link = NULL; | 478 _oops_do_mark_link = NULL; |
480 _jmethod_id = NULL; | 479 _jmethod_id = NULL; |
481 _osr_link = NULL; | 480 _osr_link = NULL; |
482 _scavenge_root_link = NULL; | 481 _scavenge_root_link = NULL; |
483 _scavenge_root_state = 0; | 482 _scavenge_root_state = 0; |
484 _saved_nmethod_link = NULL; | |
485 _compiler = NULL; | 483 _compiler = NULL; |
486 | 484 |
487 #ifdef HAVE_DTRACE_H | 485 #ifdef HAVE_DTRACE_H |
488 _trap_offset = 0; | 486 _trap_offset = 0; |
489 #endif // def HAVE_DTRACE_H | 487 #endif // def HAVE_DTRACE_H |
684 _entry_point = code_begin() + offsets->value(CodeOffsets::Entry); | 682 _entry_point = code_begin() + offsets->value(CodeOffsets::Entry); |
685 _verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry); | 683 _verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry); |
686 _osr_entry_point = NULL; | 684 _osr_entry_point = NULL; |
687 _exception_cache = NULL; | 685 _exception_cache = NULL; |
688 _pc_desc_cache.reset_to(NULL); | 686 _pc_desc_cache.reset_to(NULL); |
687 _hotness_counter = NMethodSweeper::hotness_counter_reset_val(); | |
689 | 688 |
690 code_buffer->copy_values_to(this); | 689 code_buffer->copy_values_to(this); |
691 if (ScavengeRootsInCode && detect_scavenge_root_oops()) { | 690 if (ScavengeRootsInCode && detect_scavenge_root_oops()) { |
692 CodeCache::add_scavenge_root_nmethod(this); | 691 CodeCache::add_scavenge_root_nmethod(this); |
693 Universe::heap()->register_nmethod(this); | 692 Universe::heap()->register_nmethod(this); |
768 _entry_point = code_begin() + offsets->value(CodeOffsets::Entry); | 767 _entry_point = code_begin() + offsets->value(CodeOffsets::Entry); |
769 _verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry); | 768 _verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry); |
770 _osr_entry_point = NULL; | 769 _osr_entry_point = NULL; |
771 _exception_cache = NULL; | 770 _exception_cache = NULL; |
772 _pc_desc_cache.reset_to(NULL); | 771 _pc_desc_cache.reset_to(NULL); |
772 _hotness_counter = NMethodSweeper::hotness_counter_reset_val(); | |
773 | 773 |
774 code_buffer->copy_values_to(this); | 774 code_buffer->copy_values_to(this); |
775 debug_only(verify_scavenge_root_oops()); | 775 debug_only(verify_scavenge_root_oops()); |
776 CodeCache::commit(this); | 776 CodeCache::commit(this); |
777 } | 777 } |
840 _entry_bci = entry_bci; | 840 _entry_bci = entry_bci; |
841 _compile_id = compile_id; | 841 _compile_id = compile_id; |
842 _comp_level = comp_level; | 842 _comp_level = comp_level; |
843 _compiler = compiler; | 843 _compiler = compiler; |
844 _orig_pc_offset = orig_pc_offset; | 844 _orig_pc_offset = orig_pc_offset; |
845 _hotness_counter = NMethodSweeper::hotness_counter_reset_val(); | |
845 | 846 |
846 // Section offsets | 847 // Section offsets |
847 _consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts()); | 848 _consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts()); |
848 _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); | 849 _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); |
849 | 850 |
1174 } | 1175 } |
1175 } | 1176 } |
1176 | 1177 |
1177 // This is a private interface with the sweeper. | 1178 // This is a private interface with the sweeper. |
1178 void nmethod::mark_as_seen_on_stack() { | 1179 void nmethod::mark_as_seen_on_stack() { |
1179 assert(is_not_entrant(), "must be a non-entrant method"); | 1180 assert(is_alive(), "Must be an alive method"); |
1180 // Set the traversal mark to ensure that the sweeper does 2 | 1181 // Set the traversal mark to ensure that the sweeper does 2 |
1181 // cleaning passes before moving to zombie. | 1182 // cleaning passes before moving to zombie. |
1182 set_stack_traversal_mark(NMethodSweeper::traversal_count()); | 1183 set_stack_traversal_mark(NMethodSweeper::traversal_count()); |
1183 } | 1184 } |
1184 | 1185 |
1259 // The Method* is gone at this point | 1260 // The Method* is gone at this point |
1260 assert(_method == NULL, "Tautology"); | 1261 assert(_method == NULL, "Tautology"); |
1261 | 1262 |
1262 set_osr_link(NULL); | 1263 set_osr_link(NULL); |
1263 //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods | 1264 //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods |
1264 NMethodSweeper::notify(this); | 1265 NMethodSweeper::notify(); |
1265 } | 1266 } |
1266 | 1267 |
1267 void nmethod::invalidate_osr_method() { | 1268 void nmethod::invalidate_osr_method() { |
1268 assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); | 1269 assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); |
1269 // Remove from list of active nmethods | 1270 // Remove from list of active nmethods |
1349 // This nmethod may have already been unloaded during a full GC. | 1350 // This nmethod may have already been unloaded during a full GC. |
1350 if ((state == zombie) && !is_unloaded()) { | 1351 if ((state == zombie) && !is_unloaded()) { |
1351 nmethod_needs_unregister = true; | 1352 nmethod_needs_unregister = true; |
1352 } | 1353 } |
1353 | 1354 |
1355 // Must happen before state change. Otherwise we have a race condition in | |
1356 // nmethod::can_not_entrant_be_converted(). I.e., a method can immediately | |
1357 // transition its state from 'not_entrant' to 'zombie' without having to wait | |
1358 // for stack scanning. | |
1359 if (state == not_entrant) { | |
1360 mark_as_seen_on_stack(); | |
1361 OrderAccess::storestore(); | |
1362 } | |
1363 | |
1354 // Change state | 1364 // Change state |
1355 _state = state; | 1365 _state = state; |
1356 | 1366 |
1357 // Log the transition once | 1367 // Log the transition once |
1358 log_state_change(); | 1368 log_state_change(); |
1367 if (method() != NULL && (method()->code() == this || | 1377 if (method() != NULL && (method()->code() == this || |
1368 method()->from_compiled_entry() == verified_entry_point())) { | 1378 method()->from_compiled_entry() == verified_entry_point())) { |
1369 HandleMark hm; | 1379 HandleMark hm; |
1370 method()->clear_code(); | 1380 method()->clear_code(); |
1371 } | 1381 } |
1372 | |
1373 if (state == not_entrant) { | |
1374 mark_as_seen_on_stack(); | |
1375 } | |
1376 | |
1377 } // leave critical region under Patching_lock | 1382 } // leave critical region under Patching_lock |
1378 | 1383 |
1379 // When the nmethod becomes zombie it is no longer alive so the | 1384 // When the nmethod becomes zombie it is no longer alive so the |
1380 // dependencies must be flushed. nmethods in the not_entrant | 1385 // dependencies must be flushed. nmethods in the not_entrant |
1381 // state will be flushed later when the transition to zombie | 1386 // state will be flushed later when the transition to zombie |
1414 if (TraceCreateZombies) { | 1419 if (TraceCreateZombies) { |
1415 tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie"); | 1420 tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie"); |
1416 } | 1421 } |
1417 | 1422 |
1418 // Make sweeper aware that there is a zombie method that needs to be removed | 1423 // Make sweeper aware that there is a zombie method that needs to be removed |
1419 NMethodSweeper::notify(this); | 1424 NMethodSweeper::notify(); |
1420 | 1425 |
1421 return true; | 1426 return true; |
1422 } | 1427 } |
1423 | 1428 |
1424 void nmethod::flush() { | 1429 void nmethod::flush() { |
1447 ec = next; | 1452 ec = next; |
1448 } | 1453 } |
1449 | 1454 |
1450 if (on_scavenge_root_list()) { | 1455 if (on_scavenge_root_list()) { |
1451 CodeCache::drop_scavenge_root_nmethod(this); | 1456 CodeCache::drop_scavenge_root_nmethod(this); |
1452 } | |
1453 | |
1454 if (is_speculatively_disconnected()) { | |
1455 CodeCache::remove_saved_code(this); | |
1456 } | 1457 } |
1457 | 1458 |
1458 #ifdef SHARK | 1459 #ifdef SHARK |
1459 ((SharkCompiler *) compiler())->free_compiled_method(insts_begin()); | 1460 ((SharkCompiler *) compiler())->free_compiled_method(insts_begin()); |
1460 #endif // SHARK | 1461 #endif // SHARK |