// We need a special instruction size method, since lookupswitches and tableswitches might not be // properly alligned during relocation int Relocator::rc_instr_len(int bci) { Bytecodes::Code bc= code_at(bci); switch (bc) { // In the case of switch instructions, see if we have the original // padding recorded. case Bytecodes::_tableswitch: case Bytecodes::_lookupswitch: case Bytecodes::_fast_linearswitch: case Bytecodes::_fast_binaryswitch: { int pad = get_orig_switch_pad(bci, is_opcode_lookupswitch(bc)); if (pad == -1) { return instruction_length_at(bci); } // Otherwise, depends on the switch type. switch (bc) { case Bytecodes::_tableswitch: { int lo = int_at(bci + 1 + pad + 4 * 1); int hi = int_at(bci + 1 + pad + 4 * 2); int n = hi - lo + 1; return 1 + pad + 4*(3 + n); } case Bytecodes::_lookupswitch: case Bytecodes::_fast_linearswitch: case Bytecodes::_fast_binaryswitch: { int npairs = int_at(bci + 1 + pad + 4 * 1); return 1 + pad + 4*(2 + 2*npairs); } default: ShouldNotReachHere(); } } } return instruction_length_at(bci); }
// handle lookup/table switch instructions. Called be ChangeSwitchPad class bool Relocator::handle_switch_pad(int bci, int old_pad, bool is_lookup_switch) { int ilen = rc_instr_len(bci); int new_pad = align(bci+1) - (bci+1); int pad_delta = new_pad - old_pad; if (pad_delta != 0) { int len; if (!is_lookup_switch) { int low = int_at(bci+1+old_pad+4); int high = int_at(bci+1+old_pad+8); len = high-low+1 + 3; // 3 for default, hi, lo. } else { int npairs = int_at(bci+1+old_pad+4); len = npairs*2 + 2; // 2 for default, npairs. } // Because "relocateCode" does a "changeJumps" loop, // which parses instructions to determine their length, // we need to call that before messing with the current // instruction. Since it may also overwrite the current // instruction when moving down, remember the possibly // overwritten part. // Move the code following the instruction... if (!relocate_code(bci, ilen, pad_delta)) return false; if (pad_delta < 0) { // Move the shrunken instruction down. memmove(addr_at(bci + 1 + new_pad), addr_at(bci + 1 + old_pad), len * 4 + pad_delta); memmove(addr_at(bci + 1 + new_pad + len*4 + pad_delta), _overwrite, -pad_delta); } else { assert(pad_delta > 0, "check"); // Move the expanded instruction up. memmove(addr_at(bci +1 + new_pad), addr_at(bci +1 + old_pad), len * 4); memset(addr_at(bci + 1), 0, new_pad); // pad must be 0 } } return true; }
// Print this EntryActivation and all other EntryActivation's that follow it. void EntryActivation::print_list_on(Stream* st, int indent, int index) { #if USE_DEBUG_PRINTING int last_indent = st->indentation(); st->set_indentation(indent); st->indent(); st->print("[%d] ", index); Method m = method(); m.print_value_on(st); st->cr(); for (int i = 0; i < length(); i++) { st->indent(); st->print(" "); switch(tag_at(i)) { case float_tag: st->print("(float) %f", jvm_f2d(float_at(i))); break; case double_tag: st->print("(double) %d", double_at(i)); i++; break; case long_tag: st->print("(long) "); st->print(OsMisc_jlong_format_specifier(), long_at(i)); i++; break; case obj_tag: { st->print("(obj) "); Oop obj = obj_at(i); obj.print_value_on(st); } break; case int_tag: st->print("(int) %d", int_at(i)); break; default: SHOULD_NOT_REACH_HERE(); } st->cr(); } EntryActivation mynext = next(); if (mynext.not_null()) { mynext.print_list_on(st, indent, index+1); } st->set_indentation(last_indent); #endif }
// 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); } } }
// Changes all jumps crossing "break_bci" by "delta". May enqueue things // on "rc->changes" void Relocator::change_jumps(int break_bci, int delta) { int bci = 0; Bytecodes::Code bc; // Now, adjust any affected instructions. while (bci < code_length()) { switch (bc= code_at(bci)) { 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: case Bytecodes::_goto: case Bytecodes::_jsr: change_jump(bci, bci+1, true, break_bci, delta); break; case Bytecodes::_goto_w: case Bytecodes::_jsr_w: change_jump(bci, bci+1, false, break_bci, delta); break; case Bytecodes::_tableswitch: case Bytecodes::_lookupswitch: case Bytecodes::_fast_linearswitch: case Bytecodes::_fast_binaryswitch: { int recPad = get_orig_switch_pad(bci, (bc != Bytecodes::_tableswitch)); int oldPad = (recPad != -1) ? recPad : align(bci+1) - (bci+1); if (bci > break_bci) { int new_bci = bci + delta; int newPad = align(new_bci+1) - (new_bci+1); // Do we need to check the padding? if (newPad != oldPad) { if (recPad == -1) { _changes->push(new ChangeSwitchPad(bci, oldPad, (bc != Bytecodes::_tableswitch))); } } } // Then the rest, which depend on the kind of switch. switch (bc) { case Bytecodes::_tableswitch: { change_jump(bci, bci +1 + oldPad, false, break_bci, delta); // We cannot use the Bytecode_tableswitch abstraction, since the padding might not be correct. int lo = int_at(bci + 1 + oldPad + 4 * 1); int hi = int_at(bci + 1 + oldPad + 4 * 2); int n = hi - lo + 1; for (int k = 0; k < n; k++) { change_jump(bci, bci +1 + oldPad + 4*(k+3), false, break_bci, delta); } // Special next-bci calculation here... bci += 1 + oldPad + (n+3)*4; continue; } case Bytecodes::_lookupswitch: case Bytecodes::_fast_linearswitch: case Bytecodes::_fast_binaryswitch: { change_jump(bci, bci +1 + oldPad, false, break_bci, delta); // We cannot use the Bytecode_lookupswitch abstraction, since the padding might not be correct. int npairs = int_at(bci + 1 + oldPad + 4 * 1); for (int k = 0; k < npairs; k++) { change_jump(bci, bci + 1 + oldPad + 4*(2 + 2*k + 1), false, break_bci, delta); } /* Special next-bci calculation here... */ bci += 1 + oldPad + (2 + (npairs*2))*4; continue; } default: ShouldNotReachHere(); } } default: break; } bci += rc_instr_len(bci); } }
Assembler::Register register_at(int index) const { return (Assembler::Register)int_at(index); }
int top_of_stack() const { return int_at(0); }