// The current instruction of "c" is a jump; one of its offset starts // at "offset" and is a short if "isShort" is "TRUE", // and an integer otherwise. If the jump crosses "breakPC", change // the span of the jump by "delta". void Relocator::change_jump(int bci, int offset, bool is_short, int break_bci, int delta) { int bci_delta = (is_short) ? short_at(offset) : int_at(offset); int targ = bci + bci_delta; if ((bci <= break_bci && targ > break_bci) || (bci > break_bci && targ <= break_bci)) { int new_delta; if (bci_delta > 0) new_delta = bci_delta + delta; else new_delta = bci_delta - delta; if (is_short && ((new_delta > MAX_SHORT) || new_delta < MIN_SHORT)) { push_jump_widen(bci, delta, new_delta); } else if (is_short) { short_at_put(offset, new_delta); } else { int_at_put(offset, new_delta); } } }
// 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; }
void set_register_at(int index, Assembler::Register reg) { int_at_put(index, (jint)reg); }
void set_top_of_stack(int index) { int_at_put(0, index); }