Mercurial > hg > truffle
comparison src/share/vm/code/nmethod.cpp @ 2405:3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
Reviewed-by: never, kvn
author | twisti |
---|---|
date | Mon, 28 Mar 2011 03:58:07 -0700 |
parents | c7f3d0b4570f |
children | 0654ee04b214 2aa9ddbb9e60 |
comparison
equal
deleted
inserted
replaced
2404:b40d4fa697bf | 2405:3d58a4983660 |
---|---|
26 #include "code/codeCache.hpp" | 26 #include "code/codeCache.hpp" |
27 #include "code/compiledIC.hpp" | 27 #include "code/compiledIC.hpp" |
28 #include "code/nmethod.hpp" | 28 #include "code/nmethod.hpp" |
29 #include "code/scopeDesc.hpp" | 29 #include "code/scopeDesc.hpp" |
30 #include "compiler/abstractCompiler.hpp" | 30 #include "compiler/abstractCompiler.hpp" |
31 #include "compiler/compileBroker.hpp" | |
31 #include "compiler/compileLog.hpp" | 32 #include "compiler/compileLog.hpp" |
32 #include "compiler/compilerOracle.hpp" | 33 #include "compiler/compilerOracle.hpp" |
33 #include "compiler/disassembler.hpp" | 34 #include "compiler/disassembler.hpp" |
34 #include "interpreter/bytecode.hpp" | 35 #include "interpreter/bytecode.hpp" |
35 #include "oops/methodDataOop.hpp" | 36 #include "oops/methodDataOop.hpp" |
467 #endif // def HAVE_DTRACE_H | 468 #endif // def HAVE_DTRACE_H |
468 } | 469 } |
469 | 470 |
470 | 471 |
471 nmethod* nmethod::new_native_nmethod(methodHandle method, | 472 nmethod* nmethod::new_native_nmethod(methodHandle method, |
473 int compile_id, | |
472 CodeBuffer *code_buffer, | 474 CodeBuffer *code_buffer, |
473 int vep_offset, | 475 int vep_offset, |
474 int frame_complete, | 476 int frame_complete, |
475 int frame_size, | 477 int frame_size, |
476 ByteSize basic_lock_owner_sp_offset, | 478 ByteSize basic_lock_owner_sp_offset, |
483 int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod)); | 485 int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod)); |
484 CodeOffsets offsets; | 486 CodeOffsets offsets; |
485 offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); | 487 offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); |
486 offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); | 488 offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); |
487 nm = new (native_nmethod_size) | 489 nm = new (native_nmethod_size) |
488 nmethod(method(), native_nmethod_size, &offsets, | 490 nmethod(method(), native_nmethod_size, compile_id, &offsets, |
489 code_buffer, frame_size, | 491 code_buffer, frame_size, |
490 basic_lock_owner_sp_offset, basic_lock_sp_offset, | 492 basic_lock_owner_sp_offset, basic_lock_sp_offset, |
491 oop_maps); | 493 oop_maps); |
492 NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_native_nmethod(nm)); | 494 NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_native_nmethod(nm)); |
493 if (PrintAssembly && nm != NULL) | 495 if (PrintAssembly && nm != NULL) |
608 | 610 |
609 // For native wrappers | 611 // For native wrappers |
610 nmethod::nmethod( | 612 nmethod::nmethod( |
611 methodOop method, | 613 methodOop method, |
612 int nmethod_size, | 614 int nmethod_size, |
615 int compile_id, | |
613 CodeOffsets* offsets, | 616 CodeOffsets* offsets, |
614 CodeBuffer* code_buffer, | 617 CodeBuffer* code_buffer, |
615 int frame_size, | 618 int frame_size, |
616 ByteSize basic_lock_owner_sp_offset, | 619 ByteSize basic_lock_owner_sp_offset, |
617 ByteSize basic_lock_sp_offset, | 620 ByteSize basic_lock_sp_offset, |
642 _scopes_pcs_offset = _scopes_data_offset; | 645 _scopes_pcs_offset = _scopes_data_offset; |
643 _dependencies_offset = _scopes_pcs_offset; | 646 _dependencies_offset = _scopes_pcs_offset; |
644 _handler_table_offset = _dependencies_offset; | 647 _handler_table_offset = _dependencies_offset; |
645 _nul_chk_table_offset = _handler_table_offset; | 648 _nul_chk_table_offset = _handler_table_offset; |
646 _nmethod_end_offset = _nul_chk_table_offset; | 649 _nmethod_end_offset = _nul_chk_table_offset; |
647 _compile_id = 0; // default | 650 _compile_id = compile_id; |
648 _comp_level = CompLevel_none; | 651 _comp_level = CompLevel_none; |
649 _entry_point = code_begin() + offsets->value(CodeOffsets::Entry); | 652 _entry_point = code_begin() + offsets->value(CodeOffsets::Entry); |
650 _verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry); | 653 _verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry); |
651 _osr_entry_point = NULL; | 654 _osr_entry_point = NULL; |
652 _exception_cache = NULL; | 655 _exception_cache = NULL; |
928 } | 931 } |
929 | 932 |
930 #undef LOG_OFFSET | 933 #undef LOG_OFFSET |
931 | 934 |
932 | 935 |
933 void nmethod::print_compilation(outputStream *st, const char *method_name, const char *title, | |
934 methodOop method, bool is_blocking, int compile_id, int bci, int comp_level) { | |
935 bool is_synchronized = false, has_xhandler = false, is_native = false; | |
936 int code_size = -1; | |
937 if (method != NULL) { | |
938 is_synchronized = method->is_synchronized(); | |
939 has_xhandler = method->has_exception_handler(); | |
940 is_native = method->is_native(); | |
941 code_size = method->code_size(); | |
942 } | |
943 // print compilation number | |
944 st->print("%7d %3d", (int)tty->time_stamp().milliseconds(), compile_id); | |
945 | |
946 // print method attributes | |
947 const bool is_osr = bci != InvocationEntryBci; | |
948 const char blocking_char = is_blocking ? 'b' : ' '; | |
949 const char compile_type = is_osr ? '%' : ' '; | |
950 const char sync_char = is_synchronized ? 's' : ' '; | |
951 const char exception_char = has_xhandler ? '!' : ' '; | |
952 const char native_char = is_native ? 'n' : ' '; | |
953 st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char); | |
954 if (TieredCompilation) { | |
955 st->print("%d ", comp_level); | |
956 } | |
957 | |
958 // print optional title | |
959 bool do_nl = false; | |
960 if (title != NULL) { | |
961 int tlen = (int) strlen(title); | |
962 bool do_nl = false; | |
963 if (tlen > 0 && title[tlen-1] == '\n') { tlen--; do_nl = true; } | |
964 st->print("%.*s", tlen, title); | |
965 } else { | |
966 do_nl = true; | |
967 } | |
968 | |
969 // print method name string if given | |
970 if (method_name != NULL) { | |
971 st->print(method_name); | |
972 } else { | |
973 // otherwise as the method to print itself | |
974 if (method != NULL && !Universe::heap()->is_gc_active()) { | |
975 method->print_short_name(st); | |
976 } else { | |
977 st->print("(method)"); | |
978 } | |
979 } | |
980 | |
981 if (method != NULL) { | |
982 // print osr_bci if any | |
983 if (is_osr) st->print(" @ %d", bci); | |
984 // print method size | |
985 st->print(" (%d bytes)", code_size); | |
986 } | |
987 if (do_nl) st->cr(); | |
988 } | |
989 | |
990 // Print out more verbose output usually for a newly created nmethod. | 936 // Print out more verbose output usually for a newly created nmethod. |
991 void nmethod::print_on(outputStream* st, const char* title) const { | 937 void nmethod::print_on(outputStream* st, const char* msg) const { |
992 if (st != NULL) { | 938 if (st != NULL) { |
993 ttyLocker ttyl; | 939 ttyLocker ttyl; |
994 print_compilation(st, /*method_name*/NULL, title, | 940 CompileTask::print_compilation(st, this, msg); |
995 method(), /*is_blocking*/false, | |
996 compile_id(), | |
997 is_osr_method() ? osr_entry_bci() : InvocationEntryBci, | |
998 comp_level()); | |
999 if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this); | 941 if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this); |
1000 } | 942 } |
1001 } | 943 } |
1002 | 944 |
1003 | 945 |
1307 xtty->stamp(); | 1249 xtty->stamp(); |
1308 xtty->end_elem(); | 1250 xtty->end_elem(); |
1309 } | 1251 } |
1310 } | 1252 } |
1311 if (PrintCompilation && _state != unloaded) { | 1253 if (PrintCompilation && _state != unloaded) { |
1312 print_on(tty, _state == zombie ? "made zombie " : "made not entrant "); | 1254 print_on(tty, _state == zombie ? "made zombie" : "made not entrant"); |
1313 tty->cr(); | |
1314 } | 1255 } |
1315 } | 1256 } |
1316 | 1257 |
1317 // Common functionality for both make_not_entrant and make_zombie | 1258 // Common functionality for both make_not_entrant and make_zombie |
1318 bool nmethod::make_not_entrant_or_zombie(unsigned int state) { | 1259 bool nmethod::make_not_entrant_or_zombie(unsigned int state) { |
1814 Atomic::cmpxchg_ptr(this, &_oops_do_mark_nmethods, required_mark_nmethods); | 1755 Atomic::cmpxchg_ptr(this, &_oops_do_mark_nmethods, required_mark_nmethods); |
1815 if (observed_mark_nmethods == required_mark_nmethods) | 1756 if (observed_mark_nmethods == required_mark_nmethods) |
1816 break; | 1757 break; |
1817 } | 1758 } |
1818 // Mark was clear when we first saw this guy. | 1759 // Mark was clear when we first saw this guy. |
1819 NOT_PRODUCT(if (TraceScavenge) print_on(tty, "oops_do, mark\n")); | 1760 NOT_PRODUCT(if (TraceScavenge) print_on(tty, "oops_do, mark")); |
1820 return false; | 1761 return false; |
1821 } | 1762 } |
1822 } | 1763 } |
1823 // On fall through, another racing thread marked this nmethod before we did. | 1764 // On fall through, another racing thread marked this nmethod before we did. |
1824 return true; | 1765 return true; |
1839 while (cur != NMETHOD_SENTINEL) { | 1780 while (cur != NMETHOD_SENTINEL) { |
1840 assert(cur != NULL, "not NULL-terminated"); | 1781 assert(cur != NULL, "not NULL-terminated"); |
1841 nmethod* next = cur->_oops_do_mark_link; | 1782 nmethod* next = cur->_oops_do_mark_link; |
1842 cur->_oops_do_mark_link = NULL; | 1783 cur->_oops_do_mark_link = NULL; |
1843 cur->fix_oop_relocations(); | 1784 cur->fix_oop_relocations(); |
1844 NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark\n")); | 1785 NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark")); |
1845 cur = next; | 1786 cur = next; |
1846 } | 1787 } |
1847 void* required = _oops_do_mark_nmethods; | 1788 void* required = _oops_do_mark_nmethods; |
1848 void* observed = Atomic::cmpxchg_ptr(NULL, &_oops_do_mark_nmethods, required); | 1789 void* observed = Atomic::cmpxchg_ptr(NULL, &_oops_do_mark_nmethods, required); |
1849 guarantee(observed == required, "no races in this sequential code"); | 1790 guarantee(observed == required, "no races in this sequential code"); |
2394 | 2335 |
2395 void nmethod::print() const { | 2336 void nmethod::print() const { |
2396 ResourceMark rm; | 2337 ResourceMark rm; |
2397 ttyLocker ttyl; // keep the following output all in one block | 2338 ttyLocker ttyl; // keep the following output all in one block |
2398 | 2339 |
2399 tty->print("Compiled "); | 2340 tty->print("Compiled method "); |
2400 | 2341 |
2401 if (is_compiled_by_c1()) { | 2342 if (is_compiled_by_c1()) { |
2402 tty->print("(c1) "); | 2343 tty->print("(c1) "); |
2403 } else if (is_compiled_by_c2()) { | 2344 } else if (is_compiled_by_c2()) { |
2404 tty->print("(c2) "); | 2345 tty->print("(c2) "); |
2406 tty->print("(shark) "); | 2347 tty->print("(shark) "); |
2407 } else { | 2348 } else { |
2408 tty->print("(nm) "); | 2349 tty->print("(nm) "); |
2409 } | 2350 } |
2410 | 2351 |
2411 print_on(tty, "nmethod"); | 2352 print_on(tty, NULL); |
2412 tty->cr(); | 2353 |
2413 if (WizardMode) { | 2354 if (WizardMode) { |
2414 tty->print("((nmethod*) "INTPTR_FORMAT ") ", this); | 2355 tty->print("((nmethod*) "INTPTR_FORMAT ") ", this); |
2415 tty->print(" for method " INTPTR_FORMAT , (address)method()); | 2356 tty->print(" for method " INTPTR_FORMAT , (address)method()); |
2416 tty->print(" { "); | 2357 tty->print(" { "); |
2417 if (is_in_use()) tty->print("in_use "); | 2358 if (is_in_use()) tty->print("in_use "); |
2794 } | 2735 } |
2795 | 2736 |
2796 #ifndef PRODUCT | 2737 #ifndef PRODUCT |
2797 | 2738 |
2798 void nmethod::print_value_on(outputStream* st) const { | 2739 void nmethod::print_value_on(outputStream* st) const { |
2799 print_on(st, "nmethod"); | 2740 st->print("nmethod"); |
2741 print_on(st, NULL); | |
2800 } | 2742 } |
2801 | 2743 |
2802 void nmethod::print_calls(outputStream* st) { | 2744 void nmethod::print_calls(outputStream* st) { |
2803 RelocIterator iter(this); | 2745 RelocIterator iter(this); |
2804 while (iter.next()) { | 2746 while (iter.next()) { |