// relocate a general instruction. Called by ChangeWiden class bool Relocator::handle_widen(int bci, int new_ilen, u_char inst_buffer[]) { int ilen = rc_instr_len(bci); if (!relocate_code(bci, ilen, new_ilen - ilen)) return false; // Insert new bytecode(s) for(int k = 0; k < new_ilen; k++) { code_at_put(bci + k, (Bytecodes::Code)inst_buffer[k]); } return true; }
// ------------------------------------------------------------------ // ciMethod::load_code // // Load the bytecodes and exception handler table for this method. void ciMethod::load_code() { VM_ENTRY_MARK; assert(is_loaded(), "only loaded methods have code"); methodOop me = get_methodOop(); Arena* arena = CURRENT_THREAD_ENV->arena(); // Load the bytecodes. _code = (address)arena->Amalloc(code_size()); memcpy(_code, me->code_base(), code_size()); // Revert any breakpoint bytecodes in ci's copy if (me->number_of_breakpoints() > 0) { BreakpointInfo* bp = instanceKlass::cast(me->method_holder())->breakpoints(); for (; bp != NULL; bp = bp->next()) { if (bp->match(me)) { code_at_put(bp->bci(), bp->orig_bytecode()); } } } // And load the exception table. typeArrayOop exc_table = me->exception_table(); // Allocate one extra spot in our list of exceptions. This // last entry will be used to represent the possibility that // an exception escapes the method. See ciExceptionHandlerStream // for details. _exception_handlers = (ciExceptionHandler**)arena->Amalloc(sizeof(ciExceptionHandler*) * (_handler_count + 1)); if (_handler_count > 0) { for (int i=0; i<_handler_count; i++) { int base = i*4; _exception_handlers[i] = new (arena) ciExceptionHandler( holder(), /* start */ exc_table->int_at(base), /* limit */ exc_table->int_at(base+1), /* goto pc */ exc_table->int_at(base+2), /* cp index */ exc_table->int_at(base+3)); } } // Put an entry at the end of our list to represent the possibility // of exceptional exit. _exception_handlers[_handler_count] = new (arena) ciExceptionHandler(holder(), 0, code_size(), -1, 0); if (CIPrintMethodCodes) { print_codes(); } }
// handle jump_widen instruction. Called be ChangeJumpWiden class bool Relocator::handle_jump_widen(int bci, int delta) { int ilen = rc_instr_len(bci); Bytecodes::Code bc = code_at(bci); switch (bc) { case Bytecodes::_ifeq: case Bytecodes::_ifne: case Bytecodes::_iflt: case Bytecodes::_ifge: case Bytecodes::_ifgt: case Bytecodes::_ifle: case Bytecodes::_if_icmpeq: case Bytecodes::_if_icmpne: case Bytecodes::_if_icmplt: case Bytecodes::_if_icmpge: case Bytecodes::_if_icmpgt: case Bytecodes::_if_icmple: case Bytecodes::_if_acmpeq: case Bytecodes::_if_acmpne: case Bytecodes::_ifnull: case Bytecodes::_ifnonnull: { const int goto_length = Bytecodes::length_for(Bytecodes::_goto); // If 'if' points to the next bytecode after goto, it's already handled. // it shouldn't be. assert (short_at(bci+1) != ilen+goto_length, "if relocation already handled"); assert(ilen == 3, "check length"); // Convert to 0 if <cond> goto 6 // 3 _goto 11 // 6 _goto_w <wide delta offset> // 11 <else code> const int goto_w_length = Bytecodes::length_for(Bytecodes::_goto_w); const int add_bci = goto_length + goto_w_length; if (!relocate_code(bci, 3, /*delta*/add_bci)) return false; // if bytecode points to goto_w instruction short_at_put(bci + 1, ilen + goto_length); int cbci = bci + ilen; // goto around code_at_put(cbci, Bytecodes::_goto); short_at_put(cbci + 1, add_bci); // goto_w <wide delta> cbci = cbci + goto_length; code_at_put(cbci, Bytecodes::_goto_w); if (delta > 0) { delta += 2; // goto_w is 2 bytes more than "if" code } else { delta -= ilen+goto_length; // branch starts at goto_w offset } int_at_put(cbci + 1, delta); break; } case Bytecodes::_goto: case Bytecodes::_jsr: assert(ilen == 3, "check length"); if (!relocate_code(bci, 3, 2)) return false; if (bc == Bytecodes::_goto) code_at_put(bci, Bytecodes::_goto_w); else code_at_put(bci, Bytecodes::_jsr_w); // If it's a forward jump, add 2 for the widening. if (delta > 0) delta += 2; int_at_put(bci + 1, delta); break; default: ShouldNotReachHere(); } return true; }