src/share/vm/runtime/relocator.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/runtime/relocator.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,778 @@
     1.4 +/*
     1.5 + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "classfile/stackMapTableFormat.hpp"
    1.30 +#include "interpreter/bytecodes.hpp"
    1.31 +#include "memory/metadataFactory.hpp"
    1.32 +#include "memory/oopFactory.hpp"
    1.33 +#include "memory/universe.inline.hpp"
    1.34 +#include "oops/oop.inline.hpp"
    1.35 +#include "runtime/handles.inline.hpp"
    1.36 +#include "runtime/relocator.hpp"
    1.37 +
    1.38 +#define MAX_METHOD_LENGTH  65535
    1.39 +
    1.40 +#define MAX_SHORT ((1 << 15) - 1)
    1.41 +#define MIN_SHORT (- (1 << 15))
    1.42 +
    1.43 +// Encapsulates a code change request. There are 3 types.
    1.44 +// General instruction, jump instruction, and table/lookup switches
    1.45 +//
    1.46 +class ChangeItem : public ResourceObj {
    1.47 +  int _bci;
    1.48 + public:
    1.49 +   ChangeItem(int bci) { _bci = bci; }
    1.50 +   virtual bool handle_code_change(Relocator *r) = 0;
    1.51 +
    1.52 +   // type info
    1.53 +   virtual bool is_widen()      { return false; }
    1.54 +   virtual bool is_jump_widen() { return false; }
    1.55 +   virtual bool is_switch_pad() { return false; }
    1.56 +
    1.57 +   // accessors
    1.58 +   int bci()    { return _bci; }
    1.59 +   void relocate(int break_bci, int delta) { if (_bci > break_bci) { _bci += delta; } }
    1.60 +
    1.61 +   virtual bool adjust(int bci, int delta) { return false; }
    1.62 +
    1.63 +   // debug
    1.64 +   virtual void print() = 0;
    1.65 +};
    1.66 +
    1.67 +class ChangeWiden : public ChangeItem {
    1.68 +  int              _new_ilen;    // New length of instruction at bci
    1.69 +  u_char*          _inst_buffer; // New bytecodes
    1.70 + public:
    1.71 +  ChangeWiden(int bci, int new_ilen, u_char* inst_buffer) : ChangeItem(bci) {
    1.72 +    _new_ilen = new_ilen;
    1.73 +    _inst_buffer = inst_buffer;
    1.74 +  }
    1.75 +
    1.76 +  // Callback to do instruction
    1.77 +  bool handle_code_change(Relocator *r) { return r->handle_widen(bci(), _new_ilen, _inst_buffer); };
    1.78 +
    1.79 +  bool is_widen()              { return true; }
    1.80 +
    1.81 +  void print()                 { tty->print_cr("ChangeWiden. bci: %d   New_ilen: %d", bci(), _new_ilen); }
    1.82 +};
    1.83 +
    1.84 +class ChangeJumpWiden : public ChangeItem {
    1.85 +  int _delta;  // New length of instruction at bci
    1.86 + public:
    1.87 +  ChangeJumpWiden(int bci, int delta) : ChangeItem(bci) { _delta = delta; }
    1.88 +
    1.89 +  // Callback to do instruction
    1.90 +  bool handle_code_change(Relocator *r) { return r->handle_jump_widen(bci(), _delta); };
    1.91 +
    1.92 +  bool is_jump_widen()         { return true; }
    1.93 +
    1.94 +  // If the bci matches, adjust the delta in the change jump request.
    1.95 +  bool adjust(int jump_bci, int delta) {
    1.96 +    if (bci() == jump_bci) {
    1.97 +      if (_delta > 0)
    1.98 +        _delta += delta;
    1.99 +      else
   1.100 +        _delta -= delta;
   1.101 +      return true;
   1.102 +    }
   1.103 +    return false;
   1.104 +  }
   1.105 +
   1.106 +  void print()                 { tty->print_cr("ChangeJumpWiden. bci: %d   Delta: %d", bci(), _delta); }
   1.107 +};
   1.108 +
   1.109 +class ChangeSwitchPad : public ChangeItem {
   1.110 +  int  _padding;
   1.111 +  bool _is_lookup_switch;
   1.112 + public:
   1.113 +   ChangeSwitchPad(int bci, int padding, bool is_lookup_switch) : ChangeItem(bci) {
   1.114 +     _padding = padding;
   1.115 +     _is_lookup_switch = is_lookup_switch;
   1.116 +   }
   1.117 +
   1.118 +   // Callback to do instruction
   1.119 +   bool handle_code_change(Relocator *r) { return r->handle_switch_pad(bci(), _padding, _is_lookup_switch); };
   1.120 +
   1.121 +   bool is_switch_pad()        { return true; }
   1.122 +   int  padding()              { return _padding;  }
   1.123 +   bool is_lookup_switch()     { return _is_lookup_switch; }
   1.124 +
   1.125 +   void print()                { tty->print_cr("ChangeSwitchPad. bci: %d   Padding: %d  IsLookupSwitch: %d", bci(), _padding, _is_lookup_switch); }
   1.126 +};
   1.127 +
   1.128 +//-----------------------------------------------------------------------------------------------------------
   1.129 +// Relocator code
   1.130 +
   1.131 +Relocator::Relocator(methodHandle m, RelocatorListener* listener) {
   1.132 +  set_method(m);
   1.133 +  set_code_length(method()->code_size());
   1.134 +  set_code_array(NULL);
   1.135 +  // Allocate code array and copy bytecodes
   1.136 +  if (!expand_code_array(0)) {
   1.137 +    // Should have at least MAX_METHOD_LENGTH available or the verifier
   1.138 +    // would have failed.
   1.139 +    ShouldNotReachHere();
   1.140 +  }
   1.141 +  set_compressed_line_number_table(NULL);
   1.142 +  set_compressed_line_number_table_size(0);
   1.143 +  _listener = listener;
   1.144 +}
   1.145 +
   1.146 +// size is the new size of the instruction at bci. Hence, if size is less than the current
   1.147 +// instruction sice, we will shrink the code.
   1.148 +methodHandle Relocator::insert_space_at(int bci, int size, u_char inst_buffer[], TRAPS) {
   1.149 +  _changes = new GrowableArray<ChangeItem*> (10);
   1.150 +  _changes->push(new ChangeWiden(bci, size, inst_buffer));
   1.151 +
   1.152 +  if (TraceRelocator) {
   1.153 +    tty->print_cr("Space at: %d Size: %d", bci, size);
   1.154 +    _method->print();
   1.155 +    _method->print_codes();
   1.156 +    tty->print_cr("-------------------------------------------------");
   1.157 +  }
   1.158 +
   1.159 +  if (!handle_code_changes()) return methodHandle();
   1.160 +
   1.161 +    // Construct the new method
   1.162 +  methodHandle new_method = Method::clone_with_new_data(method(),
   1.163 +                              code_array(), code_length(),
   1.164 +                              compressed_line_number_table(),
   1.165 +                              compressed_line_number_table_size(),
   1.166 +                              CHECK_(methodHandle()));
   1.167 +
   1.168 +  // Deallocate the old Method* from metadata
   1.169 +  ClassLoaderData* loader_data = method()->method_holder()->class_loader_data();
   1.170 +  loader_data->add_to_deallocate_list(method()());
   1.171 +
   1.172 +    set_method(new_method);
   1.173 +
   1.174 +  if (TraceRelocator) {
   1.175 +    tty->print_cr("-------------------------------------------------");
   1.176 +    tty->print_cr("new method");
   1.177 +    _method->print_codes();
   1.178 +  }
   1.179 +
   1.180 +  return new_method;
   1.181 +}
   1.182 +
   1.183 +
   1.184 +bool Relocator::handle_code_changes() {
   1.185 +  assert(_changes != NULL, "changes vector must be initialized");
   1.186 +
   1.187 +  while (!_changes->is_empty()) {
   1.188 +    // Inv: everything is aligned.
   1.189 +    ChangeItem* ci = _changes->first();
   1.190 +
   1.191 +    if (TraceRelocator) {
   1.192 +      ci->print();
   1.193 +    }
   1.194 +
   1.195 +    // Execute operation
   1.196 +    if (!ci->handle_code_change(this)) return false;
   1.197 +
   1.198 +    // Shuffel items up
   1.199 +    for (int index = 1; index < _changes->length(); index++) {
   1.200 +      _changes->at_put(index-1, _changes->at(index));
   1.201 +    }
   1.202 +    _changes->pop();
   1.203 +  }
   1.204 +  return true;
   1.205 +}
   1.206 +
   1.207 +
   1.208 +bool Relocator::is_opcode_lookupswitch(Bytecodes::Code bc) {
   1.209 +  switch (bc) {
   1.210 +    case Bytecodes::_tableswitch:       return false;
   1.211 +    case Bytecodes::_lookupswitch:                   // not rewritten on ia64
   1.212 +    case Bytecodes::_fast_linearswitch:              // rewritten _lookupswitch
   1.213 +    case Bytecodes::_fast_binaryswitch: return true; // rewritten _lookupswitch
   1.214 +    default: ShouldNotReachHere();
   1.215 +  }
   1.216 +  return true; // dummy
   1.217 +}
   1.218 +
   1.219 +// We need a special instruction size method, since lookupswitches and tableswitches might not be
   1.220 +// properly alligned during relocation
   1.221 +int Relocator::rc_instr_len(int bci) {
   1.222 +  Bytecodes::Code bc= code_at(bci);
   1.223 +  switch (bc) {
   1.224 +    // In the case of switch instructions, see if we have the original
   1.225 +    // padding recorded.
   1.226 +    case Bytecodes::_tableswitch:
   1.227 +    case Bytecodes::_lookupswitch:
   1.228 +    case Bytecodes::_fast_linearswitch:
   1.229 +    case Bytecodes::_fast_binaryswitch:
   1.230 +    {
   1.231 +      int pad = get_orig_switch_pad(bci, is_opcode_lookupswitch(bc));
   1.232 +      if (pad == -1) {
   1.233 +        return instruction_length_at(bci);
   1.234 +      }
   1.235 +      // Otherwise, depends on the switch type.
   1.236 +      switch (bc) {
   1.237 +        case Bytecodes::_tableswitch: {
   1.238 +          int lo = int_at(bci + 1 + pad + 4 * 1);
   1.239 +          int hi = int_at(bci + 1 + pad + 4 * 2);
   1.240 +          int n = hi - lo + 1;
   1.241 +          return 1 + pad + 4*(3 + n);
   1.242 +        }
   1.243 +        case Bytecodes::_lookupswitch:
   1.244 +        case Bytecodes::_fast_linearswitch:
   1.245 +        case Bytecodes::_fast_binaryswitch: {
   1.246 +          int npairs = int_at(bci + 1 + pad + 4 * 1);
   1.247 +          return 1 + pad + 4*(2 + 2*npairs);
   1.248 +        }
   1.249 +        default:
   1.250 +          ShouldNotReachHere();
   1.251 +      }
   1.252 +    }
   1.253 +  }
   1.254 +  return instruction_length_at(bci);
   1.255 +}
   1.256 +
   1.257 +// If a change item is recorded for "pc", with type "ct", returns the
   1.258 +// associated padding, else -1.
   1.259 +int Relocator::get_orig_switch_pad(int bci, bool is_lookup_switch) {
   1.260 +  for (int k = 0; k < _changes->length(); k++) {
   1.261 +    ChangeItem* ci = _changes->at(k);
   1.262 +    if (ci->is_switch_pad()) {
   1.263 +      ChangeSwitchPad* csp = (ChangeSwitchPad*)ci;
   1.264 +      if (csp->is_lookup_switch() == is_lookup_switch && csp->bci() == bci) {
   1.265 +        return csp->padding();
   1.266 +      }
   1.267 +    }
   1.268 +  }
   1.269 +  return -1;
   1.270 +}
   1.271 +
   1.272 +
   1.273 +// Push a ChangeJumpWiden if it doesn't already exist on the work queue,
   1.274 +// otherwise adjust the item already there by delta.  The calculation for
   1.275 +// new_delta is wrong for this because it uses the offset stored in the
   1.276 +// code stream itself which wasn't fixed when item was pushed on the work queue.
   1.277 +void Relocator::push_jump_widen(int bci, int delta, int new_delta) {
   1.278 +  for (int j = 0; j < _changes->length(); j++) {
   1.279 +    ChangeItem* ci = _changes->at(j);
   1.280 +    if (ci->adjust(bci, delta)) return;
   1.281 +  }
   1.282 +  _changes->push(new ChangeJumpWiden(bci, new_delta));
   1.283 +}
   1.284 +
   1.285 +
   1.286 +// The current instruction of "c" is a jump; one of its offset starts
   1.287 +// at "offset" and is a short if "isShort" is "TRUE",
   1.288 +// and an integer otherwise.  If the jump crosses "breakPC", change
   1.289 +// the span of the jump by "delta".
   1.290 +void Relocator::change_jump(int bci, int offset, bool is_short, int break_bci, int delta) {
   1.291 +  int bci_delta = (is_short) ? short_at(offset) : int_at(offset);
   1.292 +  int targ = bci + bci_delta;
   1.293 +
   1.294 +  if ((bci <= break_bci && targ >  break_bci) ||
   1.295 +      (bci >  break_bci && targ <= break_bci)) {
   1.296 +    int new_delta;
   1.297 +    if (bci_delta > 0)
   1.298 +      new_delta = bci_delta + delta;
   1.299 +    else
   1.300 +      new_delta = bci_delta - delta;
   1.301 +
   1.302 +    if (is_short && ((new_delta > MAX_SHORT) || new_delta < MIN_SHORT)) {
   1.303 +      push_jump_widen(bci, delta, new_delta);
   1.304 +    } else if (is_short) {
   1.305 +      short_at_put(offset, new_delta);
   1.306 +    } else {
   1.307 +      int_at_put(offset, new_delta);
   1.308 +    }
   1.309 +  }
   1.310 +}
   1.311 +
   1.312 +
   1.313 +// Changes all jumps crossing "break_bci" by "delta".  May enqueue things
   1.314 +// on "rc->changes"
   1.315 +void Relocator::change_jumps(int break_bci, int delta) {
   1.316 +  int bci = 0;
   1.317 +  Bytecodes::Code bc;
   1.318 +  // Now, adjust any affected instructions.
   1.319 +  while (bci < code_length()) {
   1.320 +    switch (bc= code_at(bci)) {
   1.321 +      case Bytecodes::_ifeq:
   1.322 +      case Bytecodes::_ifne:
   1.323 +      case Bytecodes::_iflt:
   1.324 +      case Bytecodes::_ifge:
   1.325 +      case Bytecodes::_ifgt:
   1.326 +      case Bytecodes::_ifle:
   1.327 +      case Bytecodes::_if_icmpeq:
   1.328 +      case Bytecodes::_if_icmpne:
   1.329 +      case Bytecodes::_if_icmplt:
   1.330 +      case Bytecodes::_if_icmpge:
   1.331 +      case Bytecodes::_if_icmpgt:
   1.332 +      case Bytecodes::_if_icmple:
   1.333 +      case Bytecodes::_if_acmpeq:
   1.334 +      case Bytecodes::_if_acmpne:
   1.335 +      case Bytecodes::_ifnull:
   1.336 +      case Bytecodes::_ifnonnull:
   1.337 +      case Bytecodes::_goto:
   1.338 +      case Bytecodes::_jsr:
   1.339 +        change_jump(bci, bci+1, true, break_bci, delta);
   1.340 +        break;
   1.341 +      case Bytecodes::_goto_w:
   1.342 +      case Bytecodes::_jsr_w:
   1.343 +        change_jump(bci, bci+1, false, break_bci, delta);
   1.344 +        break;
   1.345 +      case Bytecodes::_tableswitch:
   1.346 +      case Bytecodes::_lookupswitch:
   1.347 +      case Bytecodes::_fast_linearswitch:
   1.348 +      case Bytecodes::_fast_binaryswitch: {
   1.349 +        int recPad = get_orig_switch_pad(bci, (bc != Bytecodes::_tableswitch));
   1.350 +        int oldPad = (recPad != -1) ? recPad : align(bci+1) - (bci+1);
   1.351 +        if (bci > break_bci) {
   1.352 +          int new_bci = bci + delta;
   1.353 +          int newPad = align(new_bci+1) - (new_bci+1);
   1.354 +          // Do we need to check the padding?
   1.355 +          if (newPad != oldPad) {
   1.356 +            if (recPad == -1) {
   1.357 +              _changes->push(new ChangeSwitchPad(bci, oldPad, (bc != Bytecodes::_tableswitch)));
   1.358 +            }
   1.359 +          }
   1.360 +        }
   1.361 +
   1.362 +        // Then the rest, which depend on the kind of switch.
   1.363 +        switch (bc) {
   1.364 +          case Bytecodes::_tableswitch: {
   1.365 +            change_jump(bci, bci +1 + oldPad, false, break_bci, delta);
   1.366 +            // We cannot use the Bytecode_tableswitch abstraction, since the padding might not be correct.
   1.367 +            int lo = int_at(bci + 1 + oldPad + 4 * 1);
   1.368 +            int hi = int_at(bci + 1 + oldPad + 4 * 2);
   1.369 +            int n = hi - lo + 1;
   1.370 +            for (int k = 0; k < n; k++) {
   1.371 +              change_jump(bci, bci +1 + oldPad + 4*(k+3), false, break_bci, delta);
   1.372 +            }
   1.373 +            // Special next-bci calculation here...
   1.374 +            bci += 1 + oldPad + (n+3)*4;
   1.375 +            continue;
   1.376 +          }
   1.377 +          case Bytecodes::_lookupswitch:
   1.378 +          case Bytecodes::_fast_linearswitch:
   1.379 +          case Bytecodes::_fast_binaryswitch: {
   1.380 +            change_jump(bci, bci +1 + oldPad, false, break_bci, delta);
   1.381 +            // We cannot use the Bytecode_lookupswitch abstraction, since the padding might not be correct.
   1.382 +            int npairs = int_at(bci + 1 + oldPad + 4 * 1);
   1.383 +            for (int k = 0; k < npairs; k++) {
   1.384 +              change_jump(bci, bci + 1 + oldPad + 4*(2 + 2*k + 1), false, break_bci, delta);
   1.385 +            }
   1.386 +            /* Special next-bci calculation here... */
   1.387 +            bci += 1 + oldPad + (2 + (npairs*2))*4;
   1.388 +            continue;
   1.389 +          }
   1.390 +          default:
   1.391 +            ShouldNotReachHere();
   1.392 +        }
   1.393 +      }
   1.394 +      default:
   1.395 +        break;
   1.396 +    }
   1.397 +    bci += rc_instr_len(bci);
   1.398 +  }
   1.399 +}
   1.400 +
   1.401 +// The width of instruction at "pc" is changing by "delta".  Adjust the
   1.402 +// exception table, if any, of "rc->mb".
   1.403 +void Relocator::adjust_exception_table(int bci, int delta) {
   1.404 +  ExceptionTable table(_method());
   1.405 +  for (int index = 0; index < table.length(); index ++) {
   1.406 +    if (table.start_pc(index) > bci) {
   1.407 +      table.set_start_pc(index, table.start_pc(index) + delta);
   1.408 +      table.set_end_pc(index, table.end_pc(index) + delta);
   1.409 +    } else if (bci < table.end_pc(index)) {
   1.410 +      table.set_end_pc(index, table.end_pc(index) + delta);
   1.411 +    }
   1.412 +    if (table.handler_pc(index) > bci)
   1.413 +      table.set_handler_pc(index, table.handler_pc(index) + delta);
   1.414 +  }
   1.415 +}
   1.416 +
   1.417 +
   1.418 +// The width of instruction at "bci" is changing by "delta".  Adjust the line number table.
   1.419 +void Relocator::adjust_line_no_table(int bci, int delta) {
   1.420 +  if (method()->has_linenumber_table()) {
   1.421 +    CompressedLineNumberReadStream  reader(method()->compressed_linenumber_table());
   1.422 +    CompressedLineNumberWriteStream writer(64);  // plenty big for most line number tables
   1.423 +    while (reader.read_pair()) {
   1.424 +      int adjustment = (reader.bci() > bci) ? delta : 0;
   1.425 +      writer.write_pair(reader.bci() + adjustment, reader.line());
   1.426 +    }
   1.427 +    writer.write_terminator();
   1.428 +    set_compressed_line_number_table(writer.buffer());
   1.429 +    set_compressed_line_number_table_size(writer.position());
   1.430 +  }
   1.431 +}
   1.432 +
   1.433 +
   1.434 +// The width of instruction at "bci" is changing by "delta".  Adjust the local variable table.
   1.435 +void Relocator::adjust_local_var_table(int bci, int delta) {
   1.436 +  int localvariable_table_length = method()->localvariable_table_length();
   1.437 +  if (localvariable_table_length > 0) {
   1.438 +    LocalVariableTableElement* table = method()->localvariable_table_start();
   1.439 +    for (int i = 0; i < localvariable_table_length; i++) {
   1.440 +      u2 current_bci = table[i].start_bci;
   1.441 +      if (current_bci > bci) {
   1.442 +        table[i].start_bci = current_bci + delta;
   1.443 +      } else {
   1.444 +        u2 current_length = table[i].length;
   1.445 +        if (current_bci + current_length > bci) {
   1.446 +          table[i].length = current_length + delta;
   1.447 +        }
   1.448 +      }
   1.449 +    }
   1.450 +  }
   1.451 +}
   1.452 +
   1.453 +// Create a new array, copying the src array but adding a hole at
   1.454 +// the specified location
   1.455 +static Array<u1>* insert_hole_at(ClassLoaderData* loader_data,
   1.456 +    size_t where, int hole_sz, Array<u1>* src) {
   1.457 +  Thread* THREAD = Thread::current();
   1.458 +  Array<u1>* dst =
   1.459 +      MetadataFactory::new_array<u1>(loader_data, src->length() + hole_sz, 0, CHECK_NULL);
   1.460 +
   1.461 +  address src_addr = (address)src->adr_at(0);
   1.462 +  address dst_addr = (address)dst->adr_at(0);
   1.463 +
   1.464 +  memcpy(dst_addr, src_addr, where);
   1.465 +  memcpy(dst_addr + where + hole_sz,
   1.466 +         src_addr + where, src->length() - where);
   1.467 +  return dst;
   1.468 +}
   1.469 +
   1.470 +// The width of instruction at "bci" is changing by "delta".  Adjust the stack
   1.471 +// map frames.
   1.472 +void Relocator::adjust_stack_map_table(int bci, int delta) {
   1.473 +  if (method()->has_stackmap_table()) {
   1.474 +    Array<u1>* data = method()->stackmap_data();
   1.475 +    // The data in the array is a classfile representation of the stackmap table
   1.476 +    stack_map_table* sm_table =
   1.477 +        stack_map_table::at((address)data->adr_at(0));
   1.478 +
   1.479 +    int count = sm_table->number_of_entries();
   1.480 +    stack_map_frame* frame = sm_table->entries();
   1.481 +    int bci_iter = -1;
   1.482 +    bool offset_adjusted = false; // only need to adjust one offset
   1.483 +
   1.484 +    for (int i = 0; i < count; ++i) {
   1.485 +      int offset_delta = frame->offset_delta();
   1.486 +      bci_iter += offset_delta;
   1.487 +
   1.488 +      if (!offset_adjusted && bci_iter > bci) {
   1.489 +        int new_offset_delta = offset_delta + delta;
   1.490 +
   1.491 +        if (frame->is_valid_offset(new_offset_delta)) {
   1.492 +          frame->set_offset_delta(new_offset_delta);
   1.493 +        } else {
   1.494 +          assert(frame->is_same_frame() ||
   1.495 +                 frame->is_same_locals_1_stack_item_frame(),
   1.496 +                 "Frame must be one of the compressed forms");
   1.497 +          // The new delta exceeds the capacity of the 'same_frame' or
   1.498 +          // 'same_frame_1_stack_item_frame' frame types.  We need to
   1.499 +          // convert these frames to the extended versions, but the extended
   1.500 +          // version is bigger and requires more room.  So we allocate a
   1.501 +          // new array and copy the data, being sure to leave u2-sized hole
   1.502 +          // right after the 'frame_type' for the new offset field.
   1.503 +          //
   1.504 +          // We can safely ignore the reverse situation as a small delta
   1.505 +          // can still be used in an extended version of the frame.
   1.506 +
   1.507 +          size_t frame_offset = (address)frame - (address)data->adr_at(0);
   1.508 +
   1.509 +          ClassLoaderData* loader_data = method()->method_holder()->class_loader_data();
   1.510 +          Array<u1>* new_data = insert_hole_at(loader_data, frame_offset + 1, 2, data);
   1.511 +          if (new_data == NULL) {
   1.512 +            return; // out-of-memory?
   1.513 +          }
   1.514 +          // Deallocate old data
   1.515 +          MetadataFactory::free_array<u1>(loader_data, data);
   1.516 +          data = new_data;
   1.517 +
   1.518 +          address frame_addr = (address)(data->adr_at(0) + frame_offset);
   1.519 +          frame = stack_map_frame::at(frame_addr);
   1.520 +
   1.521 +
   1.522 +          // Now convert the frames in place
   1.523 +          if (frame->is_same_frame()) {
   1.524 +            same_frame_extended::create_at(frame_addr, new_offset_delta);
   1.525 +          } else {
   1.526 +            same_locals_1_stack_item_extended::create_at(
   1.527 +              frame_addr, new_offset_delta, NULL);
   1.528 +            // the verification_info_type should already be at the right spot
   1.529 +          }
   1.530 +        }
   1.531 +        offset_adjusted = true; // needs to be done only once, since subsequent
   1.532 +                                // values are offsets from the current
   1.533 +      }
   1.534 +
   1.535 +      // The stack map frame may contain verification types, if so we need to
   1.536 +      // check and update any Uninitialized type's bci (no matter where it is).
   1.537 +      int number_of_types = frame->number_of_types();
   1.538 +      verification_type_info* types = frame->types();
   1.539 +
   1.540 +      for (int i = 0; i < number_of_types; ++i) {
   1.541 +        if (types->is_uninitialized() && types->bci() > bci) {
   1.542 +          types->set_bci(types->bci() + delta);
   1.543 +        }
   1.544 +        types = types->next();
   1.545 +      }
   1.546 +
   1.547 +      // Full frame has stack values too
   1.548 +      full_frame* ff = frame->as_full_frame();
   1.549 +      if (ff != NULL) {
   1.550 +        address eol = (address)types;
   1.551 +        number_of_types = ff->stack_slots(eol);
   1.552 +        types = ff->stack(eol);
   1.553 +        for (int i = 0; i < number_of_types; ++i) {
   1.554 +          if (types->is_uninitialized() && types->bci() > bci) {
   1.555 +            types->set_bci(types->bci() + delta);
   1.556 +          }
   1.557 +          types = types->next();
   1.558 +        }
   1.559 +      }
   1.560 +
   1.561 +      frame = frame->next();
   1.562 +    }
   1.563 +
   1.564 +    method()->set_stackmap_data(data); // in case it has changed
   1.565 +  }
   1.566 +}
   1.567 +
   1.568 +
   1.569 +bool Relocator::expand_code_array(int delta) {
   1.570 +  int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100);
   1.571 +
   1.572 +  if (length > MAX_METHOD_LENGTH) {
   1.573 +    if (delta == 0 && code_length() <= MAX_METHOD_LENGTH) {
   1.574 +      length = MAX_METHOD_LENGTH;
   1.575 +    } else {
   1.576 +      return false;
   1.577 +    }
   1.578 +  }
   1.579 +
   1.580 +  unsigned char* new_code_array = NEW_RESOURCE_ARRAY(unsigned char, length);
   1.581 +  if (!new_code_array) return false;
   1.582 +
   1.583 +  // Expanding current array
   1.584 +  if (code_array() != NULL) {
   1.585 +    memcpy(new_code_array, code_array(), code_length());
   1.586 +  } else {
   1.587 +    // Initial copy. Copy directly from Method*
   1.588 +    memcpy(new_code_array, method()->code_base(), code_length());
   1.589 +  }
   1.590 +
   1.591 +  set_code_array(new_code_array);
   1.592 +  set_code_array_length(length);
   1.593 +
   1.594 +  return true;
   1.595 +}
   1.596 +
   1.597 +
   1.598 +// The instruction at "bci", whose size is "ilen", is changing size by
   1.599 +// "delta".  Reallocate, move code, recalculate jumps, and enqueue
   1.600 +// change items as necessary.
   1.601 +bool Relocator::relocate_code(int bci, int ilen, int delta) {
   1.602 +  int next_bci = bci + ilen;
   1.603 +  if (delta > 0 && code_length() + delta > code_array_length())  {
   1.604 +    // Expand allocated code space, if necessary.
   1.605 +    if (!expand_code_array(delta)) {
   1.606 +          return false;
   1.607 +    }
   1.608 +  }
   1.609 +
   1.610 +  // We require 4-byte alignment of code arrays.
   1.611 +  assert(((intptr_t)code_array() & 3) == 0, "check code alignment");
   1.612 +  // Change jumps before doing the copying; this routine requires aligned switches.
   1.613 +  change_jumps(bci, delta);
   1.614 +
   1.615 +  // In case we have shrunken a tableswitch/lookupswitch statement, we store the last
   1.616 +  // bytes that get overwritten. We have to copy the bytes after the change_jumps method
   1.617 +  // has been called, since it is likly to update last offset in a tableswitch/lookupswitch
   1.618 +  if (delta < 0) {
   1.619 +    assert(delta>=-3, "we cannot overwrite more than 3 bytes");
   1.620 +    memcpy(_overwrite, addr_at(bci + ilen + delta), -delta);
   1.621 +  }
   1.622 +
   1.623 +  memmove(addr_at(next_bci + delta), addr_at(next_bci), code_length() - next_bci);
   1.624 +  set_code_length(code_length() + delta);
   1.625 +  // Also adjust exception tables...
   1.626 +  adjust_exception_table(bci, delta);
   1.627 +  // Line number tables...
   1.628 +  adjust_line_no_table(bci, delta);
   1.629 +  // And local variable table...
   1.630 +  adjust_local_var_table(bci, delta);
   1.631 +
   1.632 +  // Adjust stack maps
   1.633 +  adjust_stack_map_table(bci, delta);
   1.634 +
   1.635 +  // Relocate the pending change stack...
   1.636 +  for (int j = 0; j < _changes->length(); j++) {
   1.637 +    ChangeItem* ci = _changes->at(j);
   1.638 +    ci->relocate(bci, delta);
   1.639 +  }
   1.640 +
   1.641 +  // Notify any listeners about code relocation
   1.642 +  notify(bci, delta, code_length());
   1.643 +
   1.644 +  return true;
   1.645 +}
   1.646 +
   1.647 +// relocate a general instruction. Called by ChangeWiden class
   1.648 +bool Relocator::handle_widen(int bci, int new_ilen, u_char inst_buffer[]) {
   1.649 +  int ilen = rc_instr_len(bci);
   1.650 +  if (!relocate_code(bci, ilen, new_ilen - ilen))
   1.651 +    return false;
   1.652 +
   1.653 +  // Insert new bytecode(s)
   1.654 +  for(int k = 0; k < new_ilen; k++) {
   1.655 +    code_at_put(bci + k, (Bytecodes::Code)inst_buffer[k]);
   1.656 +  }
   1.657 +
   1.658 +  return true;
   1.659 +}
   1.660 +
   1.661 +// handle jump_widen instruction. Called be ChangeJumpWiden class
   1.662 +bool Relocator::handle_jump_widen(int bci, int delta) {
   1.663 +  int ilen = rc_instr_len(bci);
   1.664 +
   1.665 +  Bytecodes::Code bc = code_at(bci);
   1.666 +  switch (bc) {
   1.667 +    case Bytecodes::_ifeq:
   1.668 +    case Bytecodes::_ifne:
   1.669 +    case Bytecodes::_iflt:
   1.670 +    case Bytecodes::_ifge:
   1.671 +    case Bytecodes::_ifgt:
   1.672 +    case Bytecodes::_ifle:
   1.673 +    case Bytecodes::_if_icmpeq:
   1.674 +    case Bytecodes::_if_icmpne:
   1.675 +    case Bytecodes::_if_icmplt:
   1.676 +    case Bytecodes::_if_icmpge:
   1.677 +    case Bytecodes::_if_icmpgt:
   1.678 +    case Bytecodes::_if_icmple:
   1.679 +    case Bytecodes::_if_acmpeq:
   1.680 +    case Bytecodes::_if_acmpne:
   1.681 +    case Bytecodes::_ifnull:
   1.682 +    case Bytecodes::_ifnonnull: {
   1.683 +      const int goto_length   = Bytecodes::length_for(Bytecodes::_goto);
   1.684 +
   1.685 +      // If 'if' points to the next bytecode after goto, it's already handled.
   1.686 +      // it shouldn't be.
   1.687 +      assert (short_at(bci+1) != ilen+goto_length, "if relocation already handled");
   1.688 +      assert(ilen == 3, "check length");
   1.689 +
   1.690 +      // Convert to 0 if <cond> goto 6
   1.691 +      //            3 _goto 11
   1.692 +      //            6 _goto_w <wide delta offset>
   1.693 +      //            11 <else code>
   1.694 +      const int goto_w_length = Bytecodes::length_for(Bytecodes::_goto_w);
   1.695 +      const int add_bci = goto_length + goto_w_length;
   1.696 +
   1.697 +      if (!relocate_code(bci, 3, /*delta*/add_bci)) return false;
   1.698 +
   1.699 +      // if bytecode points to goto_w instruction
   1.700 +      short_at_put(bci + 1, ilen + goto_length);
   1.701 +
   1.702 +      int cbci = bci + ilen;
   1.703 +      // goto around
   1.704 +      code_at_put(cbci, Bytecodes::_goto);
   1.705 +      short_at_put(cbci + 1, add_bci);
   1.706 +      // goto_w <wide delta>
   1.707 +      cbci = cbci + goto_length;
   1.708 +      code_at_put(cbci, Bytecodes::_goto_w);
   1.709 +      if (delta > 0) {
   1.710 +        delta += 2;                 // goto_w is 2 bytes more than "if" code
   1.711 +      } else {
   1.712 +        delta -= ilen+goto_length;  // branch starts at goto_w offset
   1.713 +      }
   1.714 +      int_at_put(cbci + 1, delta);
   1.715 +      break;
   1.716 +
   1.717 +      }
   1.718 +    case Bytecodes::_goto:
   1.719 +    case Bytecodes::_jsr:
   1.720 +      assert(ilen == 3, "check length");
   1.721 +
   1.722 +      if (!relocate_code(bci, 3, 2)) return false;
   1.723 +      if (bc == Bytecodes::_goto)
   1.724 +        code_at_put(bci, Bytecodes::_goto_w);
   1.725 +      else
   1.726 +        code_at_put(bci, Bytecodes::_jsr_w);
   1.727 +
   1.728 +      // If it's a forward jump, add 2 for the widening.
   1.729 +      if (delta > 0) delta += 2;
   1.730 +      int_at_put(bci + 1, delta);
   1.731 +      break;
   1.732 +
   1.733 +    default: ShouldNotReachHere();
   1.734 +  }
   1.735 +
   1.736 +  return true;
   1.737 +}
   1.738 +
   1.739 +// handle lookup/table switch instructions.  Called be ChangeSwitchPad class
   1.740 +bool Relocator::handle_switch_pad(int bci, int old_pad, bool is_lookup_switch) {
   1.741 +  int ilen = rc_instr_len(bci);
   1.742 +  int new_pad = align(bci+1) - (bci+1);
   1.743 +  int pad_delta = new_pad - old_pad;
   1.744 +  if (pad_delta != 0) {
   1.745 +    int len;
   1.746 +    if (!is_lookup_switch) {
   1.747 +      int low  = int_at(bci+1+old_pad+4);
   1.748 +      int high = int_at(bci+1+old_pad+8);
   1.749 +      len = high-low+1 + 3; // 3 for default, hi, lo.
   1.750 +    } else {
   1.751 +      int npairs = int_at(bci+1+old_pad+4);
   1.752 +      len = npairs*2 + 2; // 2 for default, npairs.
   1.753 +    }
   1.754 +    // Because "relocateCode" does a "changeJumps" loop,
   1.755 +    // which parses instructions to determine their length,
   1.756 +    // we need to call that before messing with the current
   1.757 +    // instruction.  Since it may also overwrite the current
   1.758 +    // instruction when moving down, remember the possibly
   1.759 +    // overwritten part.
   1.760 +
   1.761 +    // Move the code following the instruction...
   1.762 +    if (!relocate_code(bci, ilen, pad_delta)) return false;
   1.763 +
   1.764 +    if (pad_delta < 0) {
   1.765 +      // Move the shrunken instruction down.
   1.766 +      memmove(addr_at(bci + 1 + new_pad),
   1.767 +              addr_at(bci + 1 + old_pad),
   1.768 +              len * 4 + pad_delta);
   1.769 +      memmove(addr_at(bci + 1 + new_pad + len*4 + pad_delta),
   1.770 +              _overwrite, -pad_delta);
   1.771 +    } else {
   1.772 +      assert(pad_delta > 0, "check");
   1.773 +      // Move the expanded instruction up.
   1.774 +      memmove(addr_at(bci +1 + new_pad),
   1.775 +              addr_at(bci +1 + old_pad),
   1.776 +              len * 4);
   1.777 +      memset(addr_at(bci + 1), 0, new_pad); // pad must be 0
   1.778 +    }
   1.779 +  }
   1.780 +  return true;
   1.781 +}

mercurial