annotate src/share/vm/runtime/relocator.cpp @ 4731:1f114331df92

8023730: new hotspot build - hs24-b57 Reviewed-by: jcoomes
author amurillo
date Mon, 26 Aug 2013 12:06:09 -0700
parents 8150fa46d2ed
children
rev   line source
duke@0 1 /*
jiangli@3481 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
duke@0 7 * published by the Free Software Foundation.
duke@0 8 *
duke@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 13 * accompanied this code).
duke@0 14 *
duke@0 15 * You should have received a copy of the GNU General Public License version
duke@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 18 *
trims@1489 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1489 20 * or visit www.oracle.com if you need additional information or have any
trims@1489 21 * questions.
duke@0 22 *
duke@0 23 */
duke@0 24
stefank@1869 25 #include "precompiled.hpp"
stefank@1869 26 #include "classfile/stackMapTableFormat.hpp"
stefank@1869 27 #include "interpreter/bytecodes.hpp"
stefank@1869 28 #include "memory/oopFactory.hpp"
stefank@1869 29 #include "memory/universe.inline.hpp"
stefank@1869 30 #include "oops/oop.inline.hpp"
stefank@1869 31 #include "runtime/handles.inline.hpp"
stefank@1869 32 #include "runtime/relocator.hpp"
duke@0 33
duke@0 34 #define MAX_METHOD_LENGTH 65535
duke@0 35
duke@0 36 #define MAX_SHORT ((1 << 15) - 1)
duke@0 37 #define MIN_SHORT (- (1 << 15))
duke@0 38
duke@0 39 // Encapsulates a code change request. There are 3 types.
duke@0 40 // General instruction, jump instruction, and table/lookup switches
duke@0 41 //
duke@0 42 class ChangeItem : public ResourceObj {
duke@0 43 int _bci;
duke@0 44 public:
duke@0 45 ChangeItem(int bci) { _bci = bci; }
duke@0 46 virtual bool handle_code_change(Relocator *r) = 0;
duke@0 47
duke@0 48 // type info
duke@0 49 virtual bool is_widen() { return false; }
duke@0 50 virtual bool is_jump_widen() { return false; }
duke@0 51 virtual bool is_switch_pad() { return false; }
duke@0 52
duke@0 53 // accessors
duke@0 54 int bci() { return _bci; }
duke@0 55 void relocate(int break_bci, int delta) { if (_bci > break_bci) { _bci += delta; } }
duke@0 56
duke@0 57 virtual bool adjust(int bci, int delta) { return false; }
duke@0 58
duke@0 59 // debug
duke@0 60 virtual void print() = 0;
duke@0 61 };
duke@0 62
duke@0 63 class ChangeWiden : public ChangeItem {
duke@0 64 int _new_ilen; // New length of instruction at bci
duke@0 65 u_char* _inst_buffer; // New bytecodes
duke@0 66 public:
duke@0 67 ChangeWiden(int bci, int new_ilen, u_char* inst_buffer) : ChangeItem(bci) {
duke@0 68 _new_ilen = new_ilen;
duke@0 69 _inst_buffer = inst_buffer;
duke@0 70 }
duke@0 71
duke@0 72 // Callback to do instruction
duke@0 73 bool handle_code_change(Relocator *r) { return r->handle_widen(bci(), _new_ilen, _inst_buffer); };
duke@0 74
duke@0 75 bool is_widen() { return true; }
duke@0 76
duke@0 77 void print() { tty->print_cr("ChangeWiden. bci: %d New_ilen: %d", bci(), _new_ilen); }
duke@0 78 };
duke@0 79
duke@0 80 class ChangeJumpWiden : public ChangeItem {
duke@0 81 int _delta; // New length of instruction at bci
duke@0 82 public:
duke@0 83 ChangeJumpWiden(int bci, int delta) : ChangeItem(bci) { _delta = delta; }
duke@0 84
duke@0 85 // Callback to do instruction
duke@0 86 bool handle_code_change(Relocator *r) { return r->handle_jump_widen(bci(), _delta); };
duke@0 87
duke@0 88 bool is_jump_widen() { return true; }
duke@0 89
duke@0 90 // If the bci matches, adjust the delta in the change jump request.
duke@0 91 bool adjust(int jump_bci, int delta) {
duke@0 92 if (bci() == jump_bci) {
duke@0 93 if (_delta > 0)
duke@0 94 _delta += delta;
duke@0 95 else
duke@0 96 _delta -= delta;
duke@0 97 return true;
duke@0 98 }
duke@0 99 return false;
duke@0 100 }
duke@0 101
duke@0 102 void print() { tty->print_cr("ChangeJumpWiden. bci: %d Delta: %d", bci(), _delta); }
duke@0 103 };
duke@0 104
duke@0 105 class ChangeSwitchPad : public ChangeItem {
duke@0 106 int _padding;
duke@0 107 bool _is_lookup_switch;
duke@0 108 public:
duke@0 109 ChangeSwitchPad(int bci, int padding, bool is_lookup_switch) : ChangeItem(bci) {
duke@0 110 _padding = padding;
duke@0 111 _is_lookup_switch = is_lookup_switch;
duke@0 112 }
duke@0 113
duke@0 114 // Callback to do instruction
duke@0 115 bool handle_code_change(Relocator *r) { return r->handle_switch_pad(bci(), _padding, _is_lookup_switch); };
duke@0 116
duke@0 117 bool is_switch_pad() { return true; }
duke@0 118 int padding() { return _padding; }
duke@0 119 bool is_lookup_switch() { return _is_lookup_switch; }
duke@0 120
duke@0 121 void print() { tty->print_cr("ChangeSwitchPad. bci: %d Padding: %d IsLookupSwitch: %d", bci(), _padding, _is_lookup_switch); }
duke@0 122 };
duke@0 123
duke@0 124 //-----------------------------------------------------------------------------------------------------------
duke@0 125 // Relocator code
duke@0 126
duke@0 127 Relocator::Relocator(methodHandle m, RelocatorListener* listener) {
duke@0 128 set_method(m);
duke@0 129 set_code_length(method()->code_size());
duke@0 130 set_code_array(NULL);
duke@0 131 // Allocate code array and copy bytecodes
duke@0 132 if (!expand_code_array(0)) {
duke@0 133 // Should have at least MAX_METHOD_LENGTH available or the verifier
duke@0 134 // would have failed.
duke@0 135 ShouldNotReachHere();
duke@0 136 }
duke@0 137 set_compressed_line_number_table(NULL);
duke@0 138 set_compressed_line_number_table_size(0);
duke@0 139 _listener = listener;
duke@0 140 }
duke@0 141
duke@0 142 // size is the new size of the instruction at bci. Hence, if size is less than the current
duke@0 143 // instruction sice, we will shrink the code.
duke@0 144 methodHandle Relocator::insert_space_at(int bci, int size, u_char inst_buffer[], TRAPS) {
duke@0 145 _changes = new GrowableArray<ChangeItem*> (10);
duke@0 146 _changes->push(new ChangeWiden(bci, size, inst_buffer));
duke@0 147
duke@0 148 if (TraceRelocator) {
duke@0 149 tty->print_cr("Space at: %d Size: %d", bci, size);
duke@0 150 _method->print();
duke@0 151 _method->print_codes();
duke@0 152 tty->print_cr("-------------------------------------------------");
duke@0 153 }
duke@0 154
duke@0 155 if (!handle_code_changes()) return methodHandle();
duke@0 156
duke@0 157 // Construct the new method
duke@0 158 methodHandle new_method = methodOopDesc::clone_with_new_data(method(),
duke@0 159 code_array(), code_length(),
duke@0 160 compressed_line_number_table(),
duke@0 161 compressed_line_number_table_size(),
duke@0 162 CHECK_(methodHandle()));
duke@0 163 set_method(new_method);
duke@0 164
duke@0 165 if (TraceRelocator) {
duke@0 166 tty->print_cr("-------------------------------------------------");
duke@0 167 tty->print_cr("new method");
duke@0 168 _method->print_codes();
duke@0 169 }
duke@0 170
duke@0 171 return new_method;
duke@0 172 }
duke@0 173
duke@0 174
duke@0 175 bool Relocator::handle_code_changes() {
duke@0 176 assert(_changes != NULL, "changes vector must be initialized");
duke@0 177
duke@0 178 while (!_changes->is_empty()) {
duke@0 179 // Inv: everything is aligned.
duke@0 180 ChangeItem* ci = _changes->first();
duke@0 181
duke@0 182 if (TraceRelocator) {
duke@0 183 ci->print();
duke@0 184 }
duke@0 185
duke@0 186 // Execute operation
duke@0 187 if (!ci->handle_code_change(this)) return false;
duke@0 188
duke@0 189 // Shuffel items up
duke@0 190 for (int index = 1; index < _changes->length(); index++) {
duke@0 191 _changes->at_put(index-1, _changes->at(index));
duke@0 192 }
duke@0 193 _changes->pop();
duke@0 194 }
duke@0 195 return true;
duke@0 196 }
duke@0 197
duke@0 198
duke@0 199 bool Relocator::is_opcode_lookupswitch(Bytecodes::Code bc) {
duke@0 200 switch (bc) {
duke@0 201 case Bytecodes::_tableswitch: return false;
duke@0 202 case Bytecodes::_lookupswitch: // not rewritten on ia64
duke@0 203 case Bytecodes::_fast_linearswitch: // rewritten _lookupswitch
duke@0 204 case Bytecodes::_fast_binaryswitch: return true; // rewritten _lookupswitch
duke@0 205 default: ShouldNotReachHere();
duke@0 206 }
duke@0 207 return true; // dummy
duke@0 208 }
duke@0 209
duke@0 210 // We need a special instruction size method, since lookupswitches and tableswitches might not be
duke@0 211 // properly alligned during relocation
duke@0 212 int Relocator::rc_instr_len(int bci) {
duke@0 213 Bytecodes::Code bc= code_at(bci);
duke@0 214 switch (bc) {
duke@0 215 // In the case of switch instructions, see if we have the original
duke@0 216 // padding recorded.
duke@0 217 case Bytecodes::_tableswitch:
duke@0 218 case Bytecodes::_lookupswitch:
duke@0 219 case Bytecodes::_fast_linearswitch:
duke@0 220 case Bytecodes::_fast_binaryswitch:
duke@0 221 {
duke@0 222 int pad = get_orig_switch_pad(bci, is_opcode_lookupswitch(bc));
duke@0 223 if (pad == -1) {
duke@0 224 return instruction_length_at(bci);
duke@0 225 }
duke@0 226 // Otherwise, depends on the switch type.
duke@0 227 switch (bc) {
duke@0 228 case Bytecodes::_tableswitch: {
duke@0 229 int lo = int_at(bci + 1 + pad + 4 * 1);
duke@0 230 int hi = int_at(bci + 1 + pad + 4 * 2);
duke@0 231 int n = hi - lo + 1;
duke@0 232 return 1 + pad + 4*(3 + n);
duke@0 233 }
duke@0 234 case Bytecodes::_lookupswitch:
duke@0 235 case Bytecodes::_fast_linearswitch:
duke@0 236 case Bytecodes::_fast_binaryswitch: {
duke@0 237 int npairs = int_at(bci + 1 + pad + 4 * 1);
duke@0 238 return 1 + pad + 4*(2 + 2*npairs);
duke@0 239 }
duke@0 240 default:
duke@0 241 ShouldNotReachHere();
duke@0 242 }
duke@0 243 }
duke@0 244 }
duke@0 245 return instruction_length_at(bci);
duke@0 246 }
duke@0 247
duke@0 248 // If a change item is recorded for "pc", with type "ct", returns the
duke@0 249 // associated padding, else -1.
duke@0 250 int Relocator::get_orig_switch_pad(int bci, bool is_lookup_switch) {
duke@0 251 for (int k = 0; k < _changes->length(); k++) {
duke@0 252 ChangeItem* ci = _changes->at(k);
duke@0 253 if (ci->is_switch_pad()) {
duke@0 254 ChangeSwitchPad* csp = (ChangeSwitchPad*)ci;
duke@0 255 if (csp->is_lookup_switch() == is_lookup_switch && csp->bci() == bci) {
duke@0 256 return csp->padding();
duke@0 257 }
duke@0 258 }
duke@0 259 }
duke@0 260 return -1;
duke@0 261 }
duke@0 262
duke@0 263
duke@0 264 // Push a ChangeJumpWiden if it doesn't already exist on the work queue,
duke@0 265 // otherwise adjust the item already there by delta. The calculation for
duke@0 266 // new_delta is wrong for this because it uses the offset stored in the
duke@0 267 // code stream itself which wasn't fixed when item was pushed on the work queue.
duke@0 268 void Relocator::push_jump_widen(int bci, int delta, int new_delta) {
duke@0 269 for (int j = 0; j < _changes->length(); j++) {
duke@0 270 ChangeItem* ci = _changes->at(j);
duke@0 271 if (ci->adjust(bci, delta)) return;
duke@0 272 }
duke@0 273 _changes->push(new ChangeJumpWiden(bci, new_delta));
duke@0 274 }
duke@0 275
duke@0 276
duke@0 277 // The current instruction of "c" is a jump; one of its offset starts
duke@0 278 // at "offset" and is a short if "isShort" is "TRUE",
duke@0 279 // and an integer otherwise. If the jump crosses "breakPC", change
duke@0 280 // the span of the jump by "delta".
duke@0 281 void Relocator::change_jump(int bci, int offset, bool is_short, int break_bci, int delta) {
duke@0 282 int bci_delta = (is_short) ? short_at(offset) : int_at(offset);
duke@0 283 int targ = bci + bci_delta;
duke@0 284
duke@0 285 if ((bci <= break_bci && targ > break_bci) ||
duke@0 286 (bci > break_bci && targ <= break_bci)) {
duke@0 287 int new_delta;
duke@0 288 if (bci_delta > 0)
duke@0 289 new_delta = bci_delta + delta;
duke@0 290 else
duke@0 291 new_delta = bci_delta - delta;
duke@0 292
duke@0 293 if (is_short && ((new_delta > MAX_SHORT) || new_delta < MIN_SHORT)) {
duke@0 294 push_jump_widen(bci, delta, new_delta);
duke@0 295 } else if (is_short) {
duke@0 296 short_at_put(offset, new_delta);
duke@0 297 } else {
duke@0 298 int_at_put(offset, new_delta);
duke@0 299 }
duke@0 300 }
duke@0 301 }
duke@0 302
duke@0 303
duke@0 304 // Changes all jumps crossing "break_bci" by "delta". May enqueue things
duke@0 305 // on "rc->changes"
duke@0 306 void Relocator::change_jumps(int break_bci, int delta) {
duke@0 307 int bci = 0;
duke@0 308 Bytecodes::Code bc;
duke@0 309 // Now, adjust any affected instructions.
duke@0 310 while (bci < code_length()) {
duke@0 311 switch (bc= code_at(bci)) {
duke@0 312 case Bytecodes::_ifeq:
duke@0 313 case Bytecodes::_ifne:
duke@0 314 case Bytecodes::_iflt:
duke@0 315 case Bytecodes::_ifge:
duke@0 316 case Bytecodes::_ifgt:
duke@0 317 case Bytecodes::_ifle:
duke@0 318 case Bytecodes::_if_icmpeq:
duke@0 319 case Bytecodes::_if_icmpne:
duke@0 320 case Bytecodes::_if_icmplt:
duke@0 321 case Bytecodes::_if_icmpge:
duke@0 322 case Bytecodes::_if_icmpgt:
duke@0 323 case Bytecodes::_if_icmple:
duke@0 324 case Bytecodes::_if_acmpeq:
duke@0 325 case Bytecodes::_if_acmpne:
duke@0 326 case Bytecodes::_ifnull:
duke@0 327 case Bytecodes::_ifnonnull:
duke@0 328 case Bytecodes::_goto:
duke@0 329 case Bytecodes::_jsr:
duke@0 330 change_jump(bci, bci+1, true, break_bci, delta);
duke@0 331 break;
duke@0 332 case Bytecodes::_goto_w:
duke@0 333 case Bytecodes::_jsr_w:
duke@0 334 change_jump(bci, bci+1, false, break_bci, delta);
duke@0 335 break;
duke@0 336 case Bytecodes::_tableswitch:
duke@0 337 case Bytecodes::_lookupswitch:
duke@0 338 case Bytecodes::_fast_linearswitch:
duke@0 339 case Bytecodes::_fast_binaryswitch: {
duke@0 340 int recPad = get_orig_switch_pad(bci, (bc != Bytecodes::_tableswitch));
duke@0 341 int oldPad = (recPad != -1) ? recPad : align(bci+1) - (bci+1);
duke@0 342 if (bci > break_bci) {
duke@0 343 int new_bci = bci + delta;
duke@0 344 int newPad = align(new_bci+1) - (new_bci+1);
duke@0 345 // Do we need to check the padding?
duke@0 346 if (newPad != oldPad) {
duke@0 347 if (recPad == -1) {
duke@0 348 _changes->push(new ChangeSwitchPad(bci, oldPad, (bc != Bytecodes::_tableswitch)));
duke@0 349 }
duke@0 350 }
duke@0 351 }
duke@0 352
duke@0 353 // Then the rest, which depend on the kind of switch.
duke@0 354 switch (bc) {
duke@0 355 case Bytecodes::_tableswitch: {
duke@0 356 change_jump(bci, bci +1 + oldPad, false, break_bci, delta);
duke@0 357 // We cannot use the Bytecode_tableswitch abstraction, since the padding might not be correct.
duke@0 358 int lo = int_at(bci + 1 + oldPad + 4 * 1);
duke@0 359 int hi = int_at(bci + 1 + oldPad + 4 * 2);
duke@0 360 int n = hi - lo + 1;
duke@0 361 for (int k = 0; k < n; k++) {
duke@0 362 change_jump(bci, bci +1 + oldPad + 4*(k+3), false, break_bci, delta);
duke@0 363 }
duke@0 364 // Special next-bci calculation here...
duke@0 365 bci += 1 + oldPad + (n+3)*4;
duke@0 366 continue;
duke@0 367 }
duke@0 368 case Bytecodes::_lookupswitch:
duke@0 369 case Bytecodes::_fast_linearswitch:
duke@0 370 case Bytecodes::_fast_binaryswitch: {
duke@0 371 change_jump(bci, bci +1 + oldPad, false, break_bci, delta);
duke@0 372 // We cannot use the Bytecode_lookupswitch abstraction, since the padding might not be correct.
duke@0 373 int npairs = int_at(bci + 1 + oldPad + 4 * 1);
duke@0 374 for (int k = 0; k < npairs; k++) {
duke@0 375 change_jump(bci, bci + 1 + oldPad + 4*(2 + 2*k + 1), false, break_bci, delta);
duke@0 376 }
duke@0 377 /* Special next-bci calculation here... */
duke@0 378 bci += 1 + oldPad + (2 + (npairs*2))*4;
duke@0 379 continue;
duke@0 380 }
duke@0 381 default:
duke@0 382 ShouldNotReachHere();
duke@0 383 }
duke@0 384 }
duke@0 385 default:
duke@0 386 break;
duke@0 387 }
duke@0 388 bci += rc_instr_len(bci);
duke@0 389 }
duke@0 390 }
duke@0 391
duke@0 392 // The width of instruction at "pc" is changing by "delta". Adjust the
duke@0 393 // exception table, if any, of "rc->mb".
duke@0 394 void Relocator::adjust_exception_table(int bci, int delta) {
jiangli@3481 395 ExceptionTable table(_method());
jiangli@3481 396 for (int index = 0; index < table.length(); index ++) {
jiangli@3481 397 if (table.start_pc(index) > bci) {
jiangli@3481 398 table.set_start_pc(index, table.start_pc(index) + delta);
jiangli@3481 399 table.set_end_pc(index, table.end_pc(index) + delta);
jiangli@3481 400 } else if (bci < table.end_pc(index)) {
jiangli@3481 401 table.set_end_pc(index, table.end_pc(index) + delta);
duke@0 402 }
jiangli@3481 403 if (table.handler_pc(index) > bci)
jiangli@3481 404 table.set_handler_pc(index, table.handler_pc(index) + delta);
duke@0 405 }
duke@0 406 }
duke@0 407
duke@0 408
duke@0 409 // The width of instruction at "bci" is changing by "delta". Adjust the line number table.
duke@0 410 void Relocator::adjust_line_no_table(int bci, int delta) {
duke@0 411 if (method()->has_linenumber_table()) {
duke@0 412 CompressedLineNumberReadStream reader(method()->compressed_linenumber_table());
duke@0 413 CompressedLineNumberWriteStream writer(64); // plenty big for most line number tables
duke@0 414 while (reader.read_pair()) {
duke@0 415 int adjustment = (reader.bci() > bci) ? delta : 0;
duke@0 416 writer.write_pair(reader.bci() + adjustment, reader.line());
duke@0 417 }
duke@0 418 writer.write_terminator();
duke@0 419 set_compressed_line_number_table(writer.buffer());
duke@0 420 set_compressed_line_number_table_size(writer.position());
duke@0 421 }
duke@0 422 }
duke@0 423
duke@0 424
duke@0 425 // The width of instruction at "bci" is changing by "delta". Adjust the local variable table.
duke@0 426 void Relocator::adjust_local_var_table(int bci, int delta) {
duke@0 427 int localvariable_table_length = method()->localvariable_table_length();
duke@0 428 if (localvariable_table_length > 0) {
duke@0 429 LocalVariableTableElement* table = method()->localvariable_table_start();
duke@0 430 for (int i = 0; i < localvariable_table_length; i++) {
duke@0 431 u2 current_bci = table[i].start_bci;
duke@0 432 if (current_bci > bci) {
duke@0 433 table[i].start_bci = current_bci + delta;
duke@0 434 } else {
duke@0 435 u2 current_length = table[i].length;
duke@0 436 if (current_bci + current_length > bci) {
duke@0 437 table[i].length = current_length + delta;
duke@0 438 }
duke@0 439 }
duke@0 440 }
duke@0 441 }
duke@0 442 }
duke@0 443
kamg@1816 444 // Create a new array, copying the src array but adding a hole at
kamg@1816 445 // the specified location
kamg@1816 446 static typeArrayOop insert_hole_at(
kamg@1816 447 size_t where, int hole_sz, typeArrayOop src) {
kamg@1816 448 Thread* THREAD = Thread::current();
kamg@1816 449 Handle src_hnd(THREAD, src);
kamg@1816 450 typeArrayOop dst =
kamg@1816 451 oopFactory::new_permanent_byteArray(src->length() + hole_sz, CHECK_NULL);
kamg@1816 452 src = (typeArrayOop)src_hnd();
kamg@1816 453
kamg@1816 454 address src_addr = (address)src->byte_at_addr(0);
kamg@1816 455 address dst_addr = (address)dst->byte_at_addr(0);
kamg@1816 456
kamg@1816 457 memcpy(dst_addr, src_addr, where);
kamg@1816 458 memcpy(dst_addr + where + hole_sz,
kamg@1816 459 src_addr + where, src->length() - where);
kamg@1816 460 return dst;
kamg@1816 461 }
kamg@1816 462
kamg@1816 463 // The width of instruction at "bci" is changing by "delta". Adjust the stack
kamg@1816 464 // map frames.
kamg@1816 465 void Relocator::adjust_stack_map_table(int bci, int delta) {
kamg@1816 466 if (method()->has_stackmap_table()) {
kamg@1816 467 typeArrayOop data = method()->stackmap_data();
kamg@3557 468 // The data in the array is a classfile representation of the stackmap table
kamg@3557 469 stack_map_table* sm_table =
kamg@3557 470 stack_map_table::at((address)data->byte_at_addr(0));
kamg@1816 471
kamg@3557 472 int count = sm_table->number_of_entries();
kamg@3557 473 stack_map_frame* frame = sm_table->entries();
kamg@1816 474 int bci_iter = -1;
kamg@1816 475 bool offset_adjusted = false; // only need to adjust one offset
kamg@1816 476
kamg@1816 477 for (int i = 0; i < count; ++i) {
kamg@1816 478 int offset_delta = frame->offset_delta();
kamg@1816 479 bci_iter += offset_delta;
kamg@1816 480
kamg@1816 481 if (!offset_adjusted && bci_iter > bci) {
kamg@1816 482 int new_offset_delta = offset_delta + delta;
kamg@1816 483
kamg@1816 484 if (frame->is_valid_offset(new_offset_delta)) {
kamg@1816 485 frame->set_offset_delta(new_offset_delta);
kamg@1816 486 } else {
kamg@1816 487 assert(frame->is_same_frame() ||
kamg@3557 488 frame->is_same_locals_1_stack_item_frame(),
kamg@1816 489 "Frame must be one of the compressed forms");
kamg@1816 490 // The new delta exceeds the capacity of the 'same_frame' or
kamg@1816 491 // 'same_frame_1_stack_item_frame' frame types. We need to
kamg@1816 492 // convert these frames to the extended versions, but the extended
kamg@1816 493 // version is bigger and requires more room. So we allocate a
kamg@1816 494 // new array and copy the data, being sure to leave u2-sized hole
kamg@1816 495 // right after the 'frame_type' for the new offset field.
kamg@1816 496 //
kamg@1816 497 // We can safely ignore the reverse situation as a small delta
kamg@1816 498 // can still be used in an extended version of the frame.
kamg@1816 499
kamg@1816 500 size_t frame_offset = (address)frame - (address)data->byte_at_addr(0);
kamg@1816 501
kamg@1816 502 data = insert_hole_at(frame_offset + 1, 2, data);
kamg@1816 503 if (data == NULL) {
kamg@1816 504 return; // out-of-memory?
kamg@1816 505 }
kamg@1816 506
kamg@1816 507 address frame_addr = (address)(data->byte_at_addr(0) + frame_offset);
kamg@1816 508 frame = stack_map_frame::at(frame_addr);
kamg@1816 509
kamg@1816 510
kamg@1816 511 // Now convert the frames in place
kamg@1816 512 if (frame->is_same_frame()) {
kamg@1816 513 same_frame_extended::create_at(frame_addr, new_offset_delta);
kamg@1816 514 } else {
kamg@3557 515 same_locals_1_stack_item_extended::create_at(
kamg@1816 516 frame_addr, new_offset_delta, NULL);
kamg@1816 517 // the verification_info_type should already be at the right spot
kamg@1816 518 }
kamg@1816 519 }
kamg@1816 520 offset_adjusted = true; // needs to be done only once, since subsequent
kamg@1816 521 // values are offsets from the current
kamg@1816 522 }
kamg@1816 523
kamg@1816 524 // The stack map frame may contain verification types, if so we need to
kamg@1816 525 // check and update any Uninitialized type's bci (no matter where it is).
kamg@1816 526 int number_of_types = frame->number_of_types();
kamg@1816 527 verification_type_info* types = frame->types();
kamg@1816 528
kamg@1816 529 for (int i = 0; i < number_of_types; ++i) {
kamg@1816 530 if (types->is_uninitialized() && types->bci() > bci) {
kamg@1816 531 types->set_bci(types->bci() + delta);
kamg@1816 532 }
kamg@1816 533 types = types->next();
kamg@1816 534 }
kamg@1816 535
kamg@1816 536 // Full frame has stack values too
kamg@1816 537 full_frame* ff = frame->as_full_frame();
kamg@1816 538 if (ff != NULL) {
kamg@1816 539 address eol = (address)types;
kamg@1816 540 number_of_types = ff->stack_slots(eol);
kamg@1816 541 types = ff->stack(eol);
kamg@1816 542 for (int i = 0; i < number_of_types; ++i) {
kamg@1816 543 if (types->is_uninitialized() && types->bci() > bci) {
kamg@1816 544 types->set_bci(types->bci() + delta);
kamg@1816 545 }
kamg@1816 546 types = types->next();
kamg@1816 547 }
kamg@1816 548 }
kamg@1816 549
kamg@1816 550 frame = frame->next();
kamg@1816 551 }
kamg@1816 552
kamg@1816 553 method()->set_stackmap_data(data); // in case it has changed
kamg@1816 554 }
kamg@1816 555 }
kamg@1816 556
duke@0 557
duke@0 558 bool Relocator::expand_code_array(int delta) {
duke@0 559 int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100);
duke@0 560
duke@0 561 if (length > MAX_METHOD_LENGTH) {
duke@0 562 if (delta == 0 && code_length() <= MAX_METHOD_LENGTH) {
duke@0 563 length = MAX_METHOD_LENGTH;
duke@0 564 } else {
duke@0 565 return false;
duke@0 566 }
duke@0 567 }
duke@0 568
duke@0 569 unsigned char* new_code_array = NEW_RESOURCE_ARRAY(unsigned char, length);
duke@0 570 if (!new_code_array) return false;
duke@0 571
duke@0 572 // Expanding current array
duke@0 573 if (code_array() != NULL) {
duke@0 574 memcpy(new_code_array, code_array(), code_length());
duke@0 575 } else {
duke@0 576 // Initial copy. Copy directly from methodOop
duke@0 577 memcpy(new_code_array, method()->code_base(), code_length());
duke@0 578 }
duke@0 579
duke@0 580 set_code_array(new_code_array);
duke@0 581 set_code_array_length(length);
duke@0 582
duke@0 583 return true;
duke@0 584 }
duke@0 585
duke@0 586
duke@0 587 // The instruction at "bci", whose size is "ilen", is changing size by
duke@0 588 // "delta". Reallocate, move code, recalculate jumps, and enqueue
duke@0 589 // change items as necessary.
duke@0 590 bool Relocator::relocate_code(int bci, int ilen, int delta) {
duke@0 591 int next_bci = bci + ilen;
duke@0 592 if (delta > 0 && code_length() + delta > code_array_length()) {
duke@0 593 // Expand allocated code space, if necessary.
duke@0 594 if (!expand_code_array(delta)) {
duke@0 595 return false;
duke@0 596 }
duke@0 597 }
duke@0 598
duke@0 599 // We require 4-byte alignment of code arrays.
duke@0 600 assert(((intptr_t)code_array() & 3) == 0, "check code alignment");
duke@0 601 // Change jumps before doing the copying; this routine requires aligned switches.
duke@0 602 change_jumps(bci, delta);
duke@0 603
duke@0 604 // In case we have shrunken a tableswitch/lookupswitch statement, we store the last
duke@0 605 // bytes that get overwritten. We have to copy the bytes after the change_jumps method
duke@0 606 // has been called, since it is likly to update last offset in a tableswitch/lookupswitch
duke@0 607 if (delta < 0) {
duke@0 608 assert(delta>=-3, "we cannot overwrite more than 3 bytes");
duke@0 609 memcpy(_overwrite, addr_at(bci + ilen + delta), -delta);
duke@0 610 }
duke@0 611
duke@0 612 memmove(addr_at(next_bci + delta), addr_at(next_bci), code_length() - next_bci);
duke@0 613 set_code_length(code_length() + delta);
duke@0 614 // Also adjust exception tables...
duke@0 615 adjust_exception_table(bci, delta);
duke@0 616 // Line number tables...
duke@0 617 adjust_line_no_table(bci, delta);
duke@0 618 // And local variable table...
duke@0 619 adjust_local_var_table(bci, delta);
duke@0 620
kamg@1816 621 // Adjust stack maps
kamg@1816 622 adjust_stack_map_table(bci, delta);
kamg@1816 623
duke@0 624 // Relocate the pending change stack...
duke@0 625 for (int j = 0; j < _changes->length(); j++) {
duke@0 626 ChangeItem* ci = _changes->at(j);
duke@0 627 ci->relocate(bci, delta);
duke@0 628 }
duke@0 629
duke@0 630 // Notify any listeners about code relocation
duke@0 631 notify(bci, delta, code_length());
duke@0 632
duke@0 633 return true;
duke@0 634 }
duke@0 635
duke@0 636 // relocate a general instruction. Called by ChangeWiden class
duke@0 637 bool Relocator::handle_widen(int bci, int new_ilen, u_char inst_buffer[]) {
duke@0 638 int ilen = rc_instr_len(bci);
duke@0 639 if (!relocate_code(bci, ilen, new_ilen - ilen))
duke@0 640 return false;
duke@0 641
duke@0 642 // Insert new bytecode(s)
duke@0 643 for(int k = 0; k < new_ilen; k++) {
duke@0 644 code_at_put(bci + k, (Bytecodes::Code)inst_buffer[k]);
duke@0 645 }
duke@0 646
duke@0 647 return true;
duke@0 648 }
duke@0 649
duke@0 650 // handle jump_widen instruction. Called be ChangeJumpWiden class
duke@0 651 bool Relocator::handle_jump_widen(int bci, int delta) {
duke@0 652 int ilen = rc_instr_len(bci);
duke@0 653
duke@0 654 Bytecodes::Code bc = code_at(bci);
duke@0 655 switch (bc) {
duke@0 656 case Bytecodes::_ifeq:
duke@0 657 case Bytecodes::_ifne:
duke@0 658 case Bytecodes::_iflt:
duke@0 659 case Bytecodes::_ifge:
duke@0 660 case Bytecodes::_ifgt:
duke@0 661 case Bytecodes::_ifle:
duke@0 662 case Bytecodes::_if_icmpeq:
duke@0 663 case Bytecodes::_if_icmpne:
duke@0 664 case Bytecodes::_if_icmplt:
duke@0 665 case Bytecodes::_if_icmpge:
duke@0 666 case Bytecodes::_if_icmpgt:
duke@0 667 case Bytecodes::_if_icmple:
duke@0 668 case Bytecodes::_if_acmpeq:
duke@0 669 case Bytecodes::_if_acmpne:
duke@0 670 case Bytecodes::_ifnull:
duke@0 671 case Bytecodes::_ifnonnull: {
duke@0 672 const int goto_length = Bytecodes::length_for(Bytecodes::_goto);
duke@0 673
duke@0 674 // If 'if' points to the next bytecode after goto, it's already handled.
duke@0 675 // it shouldn't be.
duke@0 676 assert (short_at(bci+1) != ilen+goto_length, "if relocation already handled");
duke@0 677 assert(ilen == 3, "check length");
duke@0 678
duke@0 679 // Convert to 0 if <cond> goto 6
duke@0 680 // 3 _goto 11
duke@0 681 // 6 _goto_w <wide delta offset>
duke@0 682 // 11 <else code>
duke@0 683 const int goto_w_length = Bytecodes::length_for(Bytecodes::_goto_w);
duke@0 684 const int add_bci = goto_length + goto_w_length;
duke@0 685
duke@0 686 if (!relocate_code(bci, 3, /*delta*/add_bci)) return false;
duke@0 687
duke@0 688 // if bytecode points to goto_w instruction
duke@0 689 short_at_put(bci + 1, ilen + goto_length);
duke@0 690
duke@0 691 int cbci = bci + ilen;
duke@0 692 // goto around
duke@0 693 code_at_put(cbci, Bytecodes::_goto);
duke@0 694 short_at_put(cbci + 1, add_bci);
duke@0 695 // goto_w <wide delta>
duke@0 696 cbci = cbci + goto_length;
duke@0 697 code_at_put(cbci, Bytecodes::_goto_w);
duke@0 698 if (delta > 0) {
duke@0 699 delta += 2; // goto_w is 2 bytes more than "if" code
duke@0 700 } else {
duke@0 701 delta -= ilen+goto_length; // branch starts at goto_w offset
duke@0 702 }
duke@0 703 int_at_put(cbci + 1, delta);
duke@0 704 break;
duke@0 705
duke@0 706 }
duke@0 707 case Bytecodes::_goto:
duke@0 708 case Bytecodes::_jsr:
duke@0 709 assert(ilen == 3, "check length");
duke@0 710
duke@0 711 if (!relocate_code(bci, 3, 2)) return false;
duke@0 712 if (bc == Bytecodes::_goto)
duke@0 713 code_at_put(bci, Bytecodes::_goto_w);
duke@0 714 else
duke@0 715 code_at_put(bci, Bytecodes::_jsr_w);
duke@0 716
duke@0 717 // If it's a forward jump, add 2 for the widening.
duke@0 718 if (delta > 0) delta += 2;
duke@0 719 int_at_put(bci + 1, delta);
duke@0 720 break;
duke@0 721
duke@0 722 default: ShouldNotReachHere();
duke@0 723 }
duke@0 724
duke@0 725 return true;
duke@0 726 }
duke@0 727
duke@0 728 // handle lookup/table switch instructions. Called be ChangeSwitchPad class
duke@0 729 bool Relocator::handle_switch_pad(int bci, int old_pad, bool is_lookup_switch) {
duke@0 730 int ilen = rc_instr_len(bci);
duke@0 731 int new_pad = align(bci+1) - (bci+1);
duke@0 732 int pad_delta = new_pad - old_pad;
duke@0 733 if (pad_delta != 0) {
duke@0 734 int len;
duke@0 735 if (!is_lookup_switch) {
duke@0 736 int low = int_at(bci+1+old_pad+4);
duke@0 737 int high = int_at(bci+1+old_pad+8);
duke@0 738 len = high-low+1 + 3; // 3 for default, hi, lo.
duke@0 739 } else {
duke@0 740 int npairs = int_at(bci+1+old_pad+4);
duke@0 741 len = npairs*2 + 2; // 2 for default, npairs.
duke@0 742 }
duke@0 743 // Because "relocateCode" does a "changeJumps" loop,
duke@0 744 // which parses instructions to determine their length,
duke@0 745 // we need to call that before messing with the current
duke@0 746 // instruction. Since it may also overwrite the current
duke@0 747 // instruction when moving down, remember the possibly
duke@0 748 // overwritten part.
duke@0 749
duke@0 750 // Move the code following the instruction...
duke@0 751 if (!relocate_code(bci, ilen, pad_delta)) return false;
duke@0 752
duke@0 753 if (pad_delta < 0) {
duke@0 754 // Move the shrunken instruction down.
duke@0 755 memmove(addr_at(bci + 1 + new_pad),
duke@0 756 addr_at(bci + 1 + old_pad),
duke@0 757 len * 4 + pad_delta);
duke@0 758 memmove(addr_at(bci + 1 + new_pad + len*4 + pad_delta),
duke@0 759 _overwrite, -pad_delta);
duke@0 760 } else {
duke@0 761 assert(pad_delta > 0, "check");
duke@0 762 // Move the expanded instruction up.
duke@0 763 memmove(addr_at(bci +1 + new_pad),
duke@0 764 addr_at(bci +1 + old_pad),
duke@0 765 len * 4);
kamg@1816 766 memset(addr_at(bci + 1), 0, new_pad); // pad must be 0
duke@0 767 }
duke@0 768 }
duke@0 769 return true;
duke@0 770 }