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