--- old/src/share/vm/code/nmethod.cpp 2010-05-17 05:57:09.474808945 -0700 +++ new/src/share/vm/code/nmethod.cpp 2010-05-17 05:57:08.987720508 -0700 @@ -99,12 +99,12 @@ code_size += nm->code_size(); stub_size += nm->stub_size(); consts_size += nm->consts_size(); + oops_size += nm->oops_size(); scopes_data_size += nm->scopes_data_size(); scopes_pcs_size += nm->scopes_pcs_size(); dependencies_size += nm->dependencies_size(); handler_table_size += nm->handler_table_size(); nul_chk_table_size += nm->nul_chk_table_size(); - oops_size += nm->oops_size(); } void print_nmethod_stats() { if (nmethod_count == 0) return; @@ -114,12 +114,12 @@ if (code_size != 0) tty->print_cr(" main code = %d", code_size); if (stub_size != 0) tty->print_cr(" stub code = %d", stub_size); if (consts_size != 0) tty->print_cr(" constants = %d", consts_size); + if (oops_size != 0) tty->print_cr(" oops = %d", oops_size); if (scopes_data_size != 0) tty->print_cr(" scopes data = %d", scopes_data_size); if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %d", scopes_pcs_size); if (dependencies_size != 0) tty->print_cr(" dependencies = %d", dependencies_size); if (handler_table_size != 0) tty->print_cr(" handler table = %d", handler_table_size); if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %d", nul_chk_table_size); - if (oops_size != 0) tty->print_cr(" oops = %d", oops_size); } int native_nmethod_count; @@ -600,6 +600,7 @@ #endif // def HAVE_DTRACE_H _stub_offset = data_offset(); _consts_offset = data_offset(); + _oops_offset = data_offset(); _scopes_data_offset = data_offset(); _scopes_pcs_offset = _scopes_data_offset; _dependencies_offset = _scopes_pcs_offset; @@ -690,6 +691,7 @@ _orig_pc_offset = 0; _stub_offset = data_offset(); _consts_offset = data_offset(); + _oops_offset = data_offset(); _scopes_data_offset = data_offset(); _scopes_pcs_offset = _scopes_data_offset; _dependencies_offset = _scopes_pcs_offset; @@ -805,8 +807,9 @@ _unwind_handler_offset = -1; } _consts_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->consts()->start()); - _scopes_data_offset = data_offset(); - _scopes_pcs_offset = _scopes_data_offset + round_to(debug_info->data_size (), oopSize); + _oops_offset = data_offset(); + _scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size (), oopSize); + _scopes_pcs_offset = _scopes_data_offset + round_to(debug_info->data_size (), oopSize); _dependencies_offset = _scopes_pcs_offset + adjust_pcs_size(debug_info->pcs_size()); _handler_table_offset = _dependencies_offset + round_to(dependencies->size_in_bytes (), oopSize); _nul_chk_table_offset = _handler_table_offset + round_to(handler_table->size_in_bytes(), oopSize); @@ -990,6 +993,79 @@ } +// Promote one word from an assembly-time handle to a live embedded oop. +inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) { + if (handle == NULL || + // As a special case, IC oops are initialized to 1 or -1. + handle == (jobject) Universe::non_oop_word()) { + (*dest) = (oop) handle; + } else { + (*dest) = JNIHandles::resolve_non_null(handle); + } +} + + +void nmethod::copy_oops(GrowableArray* array) { + //assert(oops_size() == 0, "do this handshake just once, please"); + int length = array->length(); + assert((address)(oops_begin() + length) <= data_end(), "oops big enough"); + oop* dest = oops_begin(); + for (int index = 0 ; index < length; index++) { + initialize_immediate_oop(&dest[index], array->at(index)); + } + + // Now we can fix up all the oops in the code. We need to do this + // in the code because the assembler uses jobjects as placeholders. + // The code and relocations have already been initialized by the + // CodeBlob constructor, so it is valid even at this early point to + // iterate over relocations and patch the code. + fix_oop_relocations(NULL, NULL, /*initialize_immediates=*/ true); +} + + +bool nmethod::is_at_poll_return(address pc) { + RelocIterator iter(this, pc, pc+1); + while (iter.next()) { + if (iter.type() == relocInfo::poll_return_type) + return true; + } + return false; +} + + +bool nmethod::is_at_poll_or_poll_return(address pc) { + RelocIterator iter(this, pc, pc+1); + while (iter.next()) { + relocInfo::relocType t = iter.type(); + if (t == relocInfo::poll_return_type || t == relocInfo::poll_type) + return true; + } + return false; +} + + +void nmethod::fix_oop_relocations(address begin, address end, bool initialize_immediates) { + // re-patch all oop-bearing instructions, just in case some oops moved + RelocIterator iter(this, begin, end); + while (iter.next()) { + if (iter.type() == relocInfo::oop_type) { + oop_Relocation* reloc = iter.oop_reloc(); + if (initialize_immediates && reloc->oop_is_immediate()) { + oop* dest = reloc->oop_addr(); + initialize_immediate_oop(dest, (jobject) *dest); + } + // Refresh the oop-related bits of this instruction. + reloc->fix_oop_relocation(); + } + + // There must not be any interfering patches or breakpoints. + assert(!(iter.type() == relocInfo::breakpoint_type + && iter.breakpoint_reloc()->active()), + "no active breakpoint"); + } +} + + ScopeDesc* nmethod::scope_desc_at(address pc) { PcDesc* pd = pc_desc_at(pc); guarantee(pd != NULL, "scope must be present"); @@ -2292,6 +2368,10 @@ consts_begin(), consts_end(), consts_size()); + if (oops_size () > 0) tty->print_cr(" oops [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + oops_begin(), + oops_end(), + oops_size()); if (scopes_data_size () > 0) tty->print_cr(" scopes data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", scopes_data_begin(), scopes_data_end(),