Mercurial > hg > truffle
annotate src/share/vm/runtime/relocator.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | a4c7fe54bf3f |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_relocator.cpp.incl" | |
27 | |
28 #define MAX_METHOD_LENGTH 65535 | |
29 | |
30 #define MAX_SHORT ((1 << 15) - 1) | |
31 #define MIN_SHORT (- (1 << 15)) | |
32 | |
33 // Encapsulates a code change request. There are 3 types. | |
34 // General instruction, jump instruction, and table/lookup switches | |
35 // | |
36 class ChangeItem : public ResourceObj { | |
37 int _bci; | |
38 public: | |
39 ChangeItem(int bci) { _bci = bci; } | |
40 virtual bool handle_code_change(Relocator *r) = 0; | |
41 | |
42 // type info | |
43 virtual bool is_widen() { return false; } | |
44 virtual bool is_jump_widen() { return false; } | |
45 virtual bool is_switch_pad() { return false; } | |
46 | |
47 // accessors | |
48 int bci() { return _bci; } | |
49 void relocate(int break_bci, int delta) { if (_bci > break_bci) { _bci += delta; } } | |
50 | |
51 virtual bool adjust(int bci, int delta) { return false; } | |
52 | |
53 // debug | |
54 virtual void print() = 0; | |
55 }; | |
56 | |
57 class ChangeWiden : public ChangeItem { | |
58 int _new_ilen; // New length of instruction at bci | |
59 u_char* _inst_buffer; // New bytecodes | |
60 public: | |
61 ChangeWiden(int bci, int new_ilen, u_char* inst_buffer) : ChangeItem(bci) { | |
62 _new_ilen = new_ilen; | |
63 _inst_buffer = inst_buffer; | |
64 } | |
65 | |
66 // Callback to do instruction | |
67 bool handle_code_change(Relocator *r) { return r->handle_widen(bci(), _new_ilen, _inst_buffer); }; | |
68 | |
69 bool is_widen() { return true; } | |
70 | |
71 void print() { tty->print_cr("ChangeWiden. bci: %d New_ilen: %d", bci(), _new_ilen); } | |
72 }; | |
73 | |
74 class ChangeJumpWiden : public ChangeItem { | |
75 int _delta; // New length of instruction at bci | |
76 public: | |
77 ChangeJumpWiden(int bci, int delta) : ChangeItem(bci) { _delta = delta; } | |
78 | |
79 // Callback to do instruction | |
80 bool handle_code_change(Relocator *r) { return r->handle_jump_widen(bci(), _delta); }; | |
81 | |
82 bool is_jump_widen() { return true; } | |
83 | |
84 // If the bci matches, adjust the delta in the change jump request. | |
85 bool adjust(int jump_bci, int delta) { | |
86 if (bci() == jump_bci) { | |
87 if (_delta > 0) | |
88 _delta += delta; | |
89 else | |
90 _delta -= delta; | |
91 return true; | |
92 } | |
93 return false; | |
94 } | |
95 | |
96 void print() { tty->print_cr("ChangeJumpWiden. bci: %d Delta: %d", bci(), _delta); } | |
97 }; | |
98 | |
99 class ChangeSwitchPad : public ChangeItem { | |
100 int _padding; | |
101 bool _is_lookup_switch; | |
102 public: | |
103 ChangeSwitchPad(int bci, int padding, bool is_lookup_switch) : ChangeItem(bci) { | |
104 _padding = padding; | |
105 _is_lookup_switch = is_lookup_switch; | |
106 } | |
107 | |
108 // Callback to do instruction | |
109 bool handle_code_change(Relocator *r) { return r->handle_switch_pad(bci(), _padding, _is_lookup_switch); }; | |
110 | |
111 bool is_switch_pad() { return true; } | |
112 int padding() { return _padding; } | |
113 bool is_lookup_switch() { return _is_lookup_switch; } | |
114 | |
115 void print() { tty->print_cr("ChangeSwitchPad. bci: %d Padding: %d IsLookupSwitch: %d", bci(), _padding, _is_lookup_switch); } | |
116 }; | |
117 | |
118 //----------------------------------------------------------------------------------------------------------- | |
119 // Relocator code | |
120 | |
121 Relocator::Relocator(methodHandle m, RelocatorListener* listener) { | |
122 set_method(m); | |
123 set_code_length(method()->code_size()); | |
124 set_code_array(NULL); | |
125 // Allocate code array and copy bytecodes | |
126 if (!expand_code_array(0)) { | |
127 // Should have at least MAX_METHOD_LENGTH available or the verifier | |
128 // would have failed. | |
129 ShouldNotReachHere(); | |
130 } | |
131 set_compressed_line_number_table(NULL); | |
132 set_compressed_line_number_table_size(0); | |
133 _listener = listener; | |
134 } | |
135 | |
136 // size is the new size of the instruction at bci. Hence, if size is less than the current | |
137 // instruction sice, we will shrink the code. | |
138 methodHandle Relocator::insert_space_at(int bci, int size, u_char inst_buffer[], TRAPS) { | |
139 _changes = new GrowableArray<ChangeItem*> (10); | |
140 _changes->push(new ChangeWiden(bci, size, inst_buffer)); | |
141 | |
142 if (TraceRelocator) { | |
143 tty->print_cr("Space at: %d Size: %d", bci, size); | |
144 _method->print(); | |
145 _method->print_codes(); | |
146 tty->print_cr("-------------------------------------------------"); | |
147 } | |
148 | |
149 if (!handle_code_changes()) return methodHandle(); | |
150 | |
151 // Construct the new method | |
152 methodHandle new_method = methodOopDesc::clone_with_new_data(method(), | |
153 code_array(), code_length(), | |
154 compressed_line_number_table(), | |
155 compressed_line_number_table_size(), | |
156 CHECK_(methodHandle())); | |
157 set_method(new_method); | |
158 | |
159 if (TraceRelocator) { | |
160 tty->print_cr("-------------------------------------------------"); | |
161 tty->print_cr("new method"); | |
162 _method->print_codes(); | |
163 } | |
164 | |
165 return new_method; | |
166 } | |
167 | |
168 | |
169 bool Relocator::handle_code_changes() { | |
170 assert(_changes != NULL, "changes vector must be initialized"); | |
171 | |
172 while (!_changes->is_empty()) { | |
173 // Inv: everything is aligned. | |
174 ChangeItem* ci = _changes->first(); | |
175 | |
176 if (TraceRelocator) { | |
177 ci->print(); | |
178 } | |
179 | |
180 // Execute operation | |
181 if (!ci->handle_code_change(this)) return false; | |
182 | |
183 // Shuffel items up | |
184 for (int index = 1; index < _changes->length(); index++) { | |
185 _changes->at_put(index-1, _changes->at(index)); | |
186 } | |
187 _changes->pop(); | |
188 } | |
189 return true; | |
190 } | |
191 | |
192 | |
193 bool Relocator::is_opcode_lookupswitch(Bytecodes::Code bc) { | |
194 switch (bc) { | |
195 case Bytecodes::_tableswitch: return false; | |
196 case Bytecodes::_lookupswitch: // not rewritten on ia64 | |
197 case Bytecodes::_fast_linearswitch: // rewritten _lookupswitch | |
198 case Bytecodes::_fast_binaryswitch: return true; // rewritten _lookupswitch | |
199 default: ShouldNotReachHere(); | |
200 } | |
201 return true; // dummy | |
202 } | |
203 | |
204 // We need a special instruction size method, since lookupswitches and tableswitches might not be | |
205 // properly alligned during relocation | |
206 int Relocator::rc_instr_len(int bci) { | |
207 Bytecodes::Code bc= code_at(bci); | |
208 switch (bc) { | |
209 // In the case of switch instructions, see if we have the original | |
210 // padding recorded. | |
211 case Bytecodes::_tableswitch: | |
212 case Bytecodes::_lookupswitch: | |
213 case Bytecodes::_fast_linearswitch: | |
214 case Bytecodes::_fast_binaryswitch: | |
215 { | |
216 int pad = get_orig_switch_pad(bci, is_opcode_lookupswitch(bc)); | |
217 if (pad == -1) { | |
218 return instruction_length_at(bci); | |
219 } | |
220 // Otherwise, depends on the switch type. | |
221 switch (bc) { | |
222 case Bytecodes::_tableswitch: { | |
223 int lo = int_at(bci + 1 + pad + 4 * 1); | |
224 int hi = int_at(bci + 1 + pad + 4 * 2); | |
225 int n = hi - lo + 1; | |
226 return 1 + pad + 4*(3 + n); | |
227 } | |
228 case Bytecodes::_lookupswitch: | |
229 case Bytecodes::_fast_linearswitch: | |
230 case Bytecodes::_fast_binaryswitch: { | |
231 int npairs = int_at(bci + 1 + pad + 4 * 1); | |
232 return 1 + pad + 4*(2 + 2*npairs); | |
233 } | |
234 default: | |
235 ShouldNotReachHere(); | |
236 } | |
237 } | |
238 } | |
239 return instruction_length_at(bci); | |
240 } | |
241 | |
242 // If a change item is recorded for "pc", with type "ct", returns the | |
243 // associated padding, else -1. | |
244 int Relocator::get_orig_switch_pad(int bci, bool is_lookup_switch) { | |
245 for (int k = 0; k < _changes->length(); k++) { | |
246 ChangeItem* ci = _changes->at(k); | |
247 if (ci->is_switch_pad()) { | |
248 ChangeSwitchPad* csp = (ChangeSwitchPad*)ci; | |
249 if (csp->is_lookup_switch() == is_lookup_switch && csp->bci() == bci) { | |
250 return csp->padding(); | |
251 } | |
252 } | |
253 } | |
254 return -1; | |
255 } | |
256 | |
257 | |
258 // Push a ChangeJumpWiden if it doesn't already exist on the work queue, | |
259 // otherwise adjust the item already there by delta. The calculation for | |
260 // new_delta is wrong for this because it uses the offset stored in the | |
261 // code stream itself which wasn't fixed when item was pushed on the work queue. | |
262 void Relocator::push_jump_widen(int bci, int delta, int new_delta) { | |
263 for (int j = 0; j < _changes->length(); j++) { | |
264 ChangeItem* ci = _changes->at(j); | |
265 if (ci->adjust(bci, delta)) return; | |
266 } | |
267 _changes->push(new ChangeJumpWiden(bci, new_delta)); | |
268 } | |
269 | |
270 | |
271 // The current instruction of "c" is a jump; one of its offset starts | |
272 // at "offset" and is a short if "isShort" is "TRUE", | |
273 // and an integer otherwise. If the jump crosses "breakPC", change | |
274 // the span of the jump by "delta". | |
275 void Relocator::change_jump(int bci, int offset, bool is_short, int break_bci, int delta) { | |
276 int bci_delta = (is_short) ? short_at(offset) : int_at(offset); | |
277 int targ = bci + bci_delta; | |
278 | |
279 if ((bci <= break_bci && targ > break_bci) || | |
280 (bci > break_bci && targ <= break_bci)) { | |
281 int new_delta; | |
282 if (bci_delta > 0) | |
283 new_delta = bci_delta + delta; | |
284 else | |
285 new_delta = bci_delta - delta; | |
286 | |
287 if (is_short && ((new_delta > MAX_SHORT) || new_delta < MIN_SHORT)) { | |
288 push_jump_widen(bci, delta, new_delta); | |
289 } else if (is_short) { | |
290 short_at_put(offset, new_delta); | |
291 } else { | |
292 int_at_put(offset, new_delta); | |
293 } | |
294 } | |
295 } | |
296 | |
297 | |
298 // Changes all jumps crossing "break_bci" by "delta". May enqueue things | |
299 // on "rc->changes" | |
300 void Relocator::change_jumps(int break_bci, int delta) { | |
301 int bci = 0; | |
302 Bytecodes::Code bc; | |
303 // Now, adjust any affected instructions. | |
304 while (bci < code_length()) { | |
305 switch (bc= code_at(bci)) { | |
306 case Bytecodes::_ifeq: | |
307 case Bytecodes::_ifne: | |
308 case Bytecodes::_iflt: | |
309 case Bytecodes::_ifge: | |
310 case Bytecodes::_ifgt: | |
311 case Bytecodes::_ifle: | |
312 case Bytecodes::_if_icmpeq: | |
313 case Bytecodes::_if_icmpne: | |
314 case Bytecodes::_if_icmplt: | |
315 case Bytecodes::_if_icmpge: | |
316 case Bytecodes::_if_icmpgt: | |
317 case Bytecodes::_if_icmple: | |
318 case Bytecodes::_if_acmpeq: | |
319 case Bytecodes::_if_acmpne: | |
320 case Bytecodes::_ifnull: | |
321 case Bytecodes::_ifnonnull: | |
322 case Bytecodes::_goto: | |
323 case Bytecodes::_jsr: | |
324 change_jump(bci, bci+1, true, break_bci, delta); | |
325 break; | |
326 case Bytecodes::_goto_w: | |
327 case Bytecodes::_jsr_w: | |
328 change_jump(bci, bci+1, false, break_bci, delta); | |
329 break; | |
330 case Bytecodes::_tableswitch: | |
331 case Bytecodes::_lookupswitch: | |
332 case Bytecodes::_fast_linearswitch: | |
333 case Bytecodes::_fast_binaryswitch: { | |
334 int recPad = get_orig_switch_pad(bci, (bc != Bytecodes::_tableswitch)); | |
335 int oldPad = (recPad != -1) ? recPad : align(bci+1) - (bci+1); | |
336 if (bci > break_bci) { | |
337 int new_bci = bci + delta; | |
338 int newPad = align(new_bci+1) - (new_bci+1); | |
339 // Do we need to check the padding? | |
340 if (newPad != oldPad) { | |
341 if (recPad == -1) { | |
342 _changes->push(new ChangeSwitchPad(bci, oldPad, (bc != Bytecodes::_tableswitch))); | |
343 } | |
344 } | |
345 } | |
346 | |
347 // Then the rest, which depend on the kind of switch. | |
348 switch (bc) { | |
349 case Bytecodes::_tableswitch: { | |
350 change_jump(bci, bci +1 + oldPad, false, break_bci, delta); | |
351 // We cannot use the Bytecode_tableswitch abstraction, since the padding might not be correct. | |
352 int lo = int_at(bci + 1 + oldPad + 4 * 1); | |
353 int hi = int_at(bci + 1 + oldPad + 4 * 2); | |
354 int n = hi - lo + 1; | |
355 for (int k = 0; k < n; k++) { | |
356 change_jump(bci, bci +1 + oldPad + 4*(k+3), false, break_bci, delta); | |
357 } | |
358 // Special next-bci calculation here... | |
359 bci += 1 + oldPad + (n+3)*4; | |
360 continue; | |
361 } | |
362 case Bytecodes::_lookupswitch: | |
363 case Bytecodes::_fast_linearswitch: | |
364 case Bytecodes::_fast_binaryswitch: { | |
365 change_jump(bci, bci +1 + oldPad, false, break_bci, delta); | |
366 // We cannot use the Bytecode_lookupswitch abstraction, since the padding might not be correct. | |
367 int npairs = int_at(bci + 1 + oldPad + 4 * 1); | |
368 for (int k = 0; k < npairs; k++) { | |
369 change_jump(bci, bci + 1 + oldPad + 4*(2 + 2*k + 1), false, break_bci, delta); | |
370 } | |
371 /* Special next-bci calculation here... */ | |
372 bci += 1 + oldPad + (2 + (npairs*2))*4; | |
373 continue; | |
374 } | |
375 default: | |
376 ShouldNotReachHere(); | |
377 } | |
378 } | |
379 default: | |
380 break; | |
381 } | |
382 bci += rc_instr_len(bci); | |
383 } | |
384 } | |
385 | |
386 // The width of instruction at "pc" is changing by "delta". Adjust the | |
387 // exception table, if any, of "rc->mb". | |
388 void Relocator::adjust_exception_table(int bci, int delta) { | |
389 typeArrayOop table = method()->exception_table(); | |
390 for (int index = 0; index < table->length(); index +=4) { | |
391 if (table->int_at(index) > bci) { | |
392 table->int_at_put(index+0, table->int_at(index+0) + delta); | |
393 table->int_at_put(index+1, table->int_at(index+1) + delta); | |
394 } else if (bci < table->int_at(index+1)) { | |
395 table->int_at_put(index+1, table->int_at(index+1) + delta); | |
396 } | |
397 if (table->int_at(index+2) > bci) | |
398 table->int_at_put(index+2, table->int_at(index+2) + delta); | |
399 } | |
400 } | |
401 | |
402 | |
403 // The width of instruction at "bci" is changing by "delta". Adjust the line number table. | |
404 void Relocator::adjust_line_no_table(int bci, int delta) { | |
405 if (method()->has_linenumber_table()) { | |
406 CompressedLineNumberReadStream reader(method()->compressed_linenumber_table()); | |
407 CompressedLineNumberWriteStream writer(64); // plenty big for most line number tables | |
408 while (reader.read_pair()) { | |
409 int adjustment = (reader.bci() > bci) ? delta : 0; | |
410 writer.write_pair(reader.bci() + adjustment, reader.line()); | |
411 } | |
412 writer.write_terminator(); | |
413 set_compressed_line_number_table(writer.buffer()); | |
414 set_compressed_line_number_table_size(writer.position()); | |
415 } | |
416 } | |
417 | |
418 | |
419 // The width of instruction at "bci" is changing by "delta". Adjust the local variable table. | |
420 void Relocator::adjust_local_var_table(int bci, int delta) { | |
421 int localvariable_table_length = method()->localvariable_table_length(); | |
422 if (localvariable_table_length > 0) { | |
423 LocalVariableTableElement* table = method()->localvariable_table_start(); | |
424 for (int i = 0; i < localvariable_table_length; i++) { | |
425 u2 current_bci = table[i].start_bci; | |
426 if (current_bci > bci) { | |
427 table[i].start_bci = current_bci + delta; | |
428 } else { | |
429 u2 current_length = table[i].length; | |
430 if (current_bci + current_length > bci) { | |
431 table[i].length = current_length + delta; | |
432 } | |
433 } | |
434 } | |
435 } | |
436 } | |
437 | |
438 | |
439 bool Relocator::expand_code_array(int delta) { | |
440 int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100); | |
441 | |
442 if (length > MAX_METHOD_LENGTH) { | |
443 if (delta == 0 && code_length() <= MAX_METHOD_LENGTH) { | |
444 length = MAX_METHOD_LENGTH; | |
445 } else { | |
446 return false; | |
447 } | |
448 } | |
449 | |
450 unsigned char* new_code_array = NEW_RESOURCE_ARRAY(unsigned char, length); | |
451 if (!new_code_array) return false; | |
452 | |
453 // Expanding current array | |
454 if (code_array() != NULL) { | |
455 memcpy(new_code_array, code_array(), code_length()); | |
456 } else { | |
457 // Initial copy. Copy directly from methodOop | |
458 memcpy(new_code_array, method()->code_base(), code_length()); | |
459 } | |
460 | |
461 set_code_array(new_code_array); | |
462 set_code_array_length(length); | |
463 | |
464 return true; | |
465 } | |
466 | |
467 | |
468 // The instruction at "bci", whose size is "ilen", is changing size by | |
469 // "delta". Reallocate, move code, recalculate jumps, and enqueue | |
470 // change items as necessary. | |
471 bool Relocator::relocate_code(int bci, int ilen, int delta) { | |
472 int next_bci = bci + ilen; | |
473 if (delta > 0 && code_length() + delta > code_array_length()) { | |
474 // Expand allocated code space, if necessary. | |
475 if (!expand_code_array(delta)) { | |
476 return false; | |
477 } | |
478 } | |
479 | |
480 // We require 4-byte alignment of code arrays. | |
481 assert(((intptr_t)code_array() & 3) == 0, "check code alignment"); | |
482 // Change jumps before doing the copying; this routine requires aligned switches. | |
483 change_jumps(bci, delta); | |
484 | |
485 // In case we have shrunken a tableswitch/lookupswitch statement, we store the last | |
486 // bytes that get overwritten. We have to copy the bytes after the change_jumps method | |
487 // has been called, since it is likly to update last offset in a tableswitch/lookupswitch | |
488 if (delta < 0) { | |
489 assert(delta>=-3, "we cannot overwrite more than 3 bytes"); | |
490 memcpy(_overwrite, addr_at(bci + ilen + delta), -delta); | |
491 } | |
492 | |
493 memmove(addr_at(next_bci + delta), addr_at(next_bci), code_length() - next_bci); | |
494 set_code_length(code_length() + delta); | |
495 // Also adjust exception tables... | |
496 adjust_exception_table(bci, delta); | |
497 // Line number tables... | |
498 adjust_line_no_table(bci, delta); | |
499 // And local variable table... | |
500 adjust_local_var_table(bci, delta); | |
501 | |
502 // Relocate the pending change stack... | |
503 for (int j = 0; j < _changes->length(); j++) { | |
504 ChangeItem* ci = _changes->at(j); | |
505 ci->relocate(bci, delta); | |
506 } | |
507 | |
508 // Notify any listeners about code relocation | |
509 notify(bci, delta, code_length()); | |
510 | |
511 return true; | |
512 } | |
513 | |
514 // relocate a general instruction. Called by ChangeWiden class | |
515 bool Relocator::handle_widen(int bci, int new_ilen, u_char inst_buffer[]) { | |
516 int ilen = rc_instr_len(bci); | |
517 if (!relocate_code(bci, ilen, new_ilen - ilen)) | |
518 return false; | |
519 | |
520 // Insert new bytecode(s) | |
521 for(int k = 0; k < new_ilen; k++) { | |
522 code_at_put(bci + k, (Bytecodes::Code)inst_buffer[k]); | |
523 } | |
524 | |
525 return true; | |
526 } | |
527 | |
528 // handle jump_widen instruction. Called be ChangeJumpWiden class | |
529 bool Relocator::handle_jump_widen(int bci, int delta) { | |
530 int ilen = rc_instr_len(bci); | |
531 | |
532 Bytecodes::Code bc = code_at(bci); | |
533 switch (bc) { | |
534 case Bytecodes::_ifeq: | |
535 case Bytecodes::_ifne: | |
536 case Bytecodes::_iflt: | |
537 case Bytecodes::_ifge: | |
538 case Bytecodes::_ifgt: | |
539 case Bytecodes::_ifle: | |
540 case Bytecodes::_if_icmpeq: | |
541 case Bytecodes::_if_icmpne: | |
542 case Bytecodes::_if_icmplt: | |
543 case Bytecodes::_if_icmpge: | |
544 case Bytecodes::_if_icmpgt: | |
545 case Bytecodes::_if_icmple: | |
546 case Bytecodes::_if_acmpeq: | |
547 case Bytecodes::_if_acmpne: | |
548 case Bytecodes::_ifnull: | |
549 case Bytecodes::_ifnonnull: { | |
550 const int goto_length = Bytecodes::length_for(Bytecodes::_goto); | |
551 | |
552 // If 'if' points to the next bytecode after goto, it's already handled. | |
553 // it shouldn't be. | |
554 assert (short_at(bci+1) != ilen+goto_length, "if relocation already handled"); | |
555 assert(ilen == 3, "check length"); | |
556 | |
557 // Convert to 0 if <cond> goto 6 | |
558 // 3 _goto 11 | |
559 // 6 _goto_w <wide delta offset> | |
560 // 11 <else code> | |
561 const int goto_w_length = Bytecodes::length_for(Bytecodes::_goto_w); | |
562 const int add_bci = goto_length + goto_w_length; | |
563 | |
564 if (!relocate_code(bci, 3, /*delta*/add_bci)) return false; | |
565 | |
566 // if bytecode points to goto_w instruction | |
567 short_at_put(bci + 1, ilen + goto_length); | |
568 | |
569 int cbci = bci + ilen; | |
570 // goto around | |
571 code_at_put(cbci, Bytecodes::_goto); | |
572 short_at_put(cbci + 1, add_bci); | |
573 // goto_w <wide delta> | |
574 cbci = cbci + goto_length; | |
575 code_at_put(cbci, Bytecodes::_goto_w); | |
576 if (delta > 0) { | |
577 delta += 2; // goto_w is 2 bytes more than "if" code | |
578 } else { | |
579 delta -= ilen+goto_length; // branch starts at goto_w offset | |
580 } | |
581 int_at_put(cbci + 1, delta); | |
582 break; | |
583 | |
584 } | |
585 case Bytecodes::_goto: | |
586 case Bytecodes::_jsr: | |
587 assert(ilen == 3, "check length"); | |
588 | |
589 if (!relocate_code(bci, 3, 2)) return false; | |
590 if (bc == Bytecodes::_goto) | |
591 code_at_put(bci, Bytecodes::_goto_w); | |
592 else | |
593 code_at_put(bci, Bytecodes::_jsr_w); | |
594 | |
595 // If it's a forward jump, add 2 for the widening. | |
596 if (delta > 0) delta += 2; | |
597 int_at_put(bci + 1, delta); | |
598 break; | |
599 | |
600 default: ShouldNotReachHere(); | |
601 } | |
602 | |
603 return true; | |
604 } | |
605 | |
606 // handle lookup/table switch instructions. Called be ChangeSwitchPad class | |
607 bool Relocator::handle_switch_pad(int bci, int old_pad, bool is_lookup_switch) { | |
608 int ilen = rc_instr_len(bci); | |
609 int new_pad = align(bci+1) - (bci+1); | |
610 int pad_delta = new_pad - old_pad; | |
611 if (pad_delta != 0) { | |
612 int len; | |
613 if (!is_lookup_switch) { | |
614 int low = int_at(bci+1+old_pad+4); | |
615 int high = int_at(bci+1+old_pad+8); | |
616 len = high-low+1 + 3; // 3 for default, hi, lo. | |
617 } else { | |
618 int npairs = int_at(bci+1+old_pad+4); | |
619 len = npairs*2 + 2; // 2 for default, npairs. | |
620 } | |
621 // Because "relocateCode" does a "changeJumps" loop, | |
622 // which parses instructions to determine their length, | |
623 // we need to call that before messing with the current | |
624 // instruction. Since it may also overwrite the current | |
625 // instruction when moving down, remember the possibly | |
626 // overwritten part. | |
627 | |
628 // Move the code following the instruction... | |
629 if (!relocate_code(bci, ilen, pad_delta)) return false; | |
630 | |
631 if (pad_delta < 0) { | |
632 // Move the shrunken instruction down. | |
633 memmove(addr_at(bci + 1 + new_pad), | |
634 addr_at(bci + 1 + old_pad), | |
635 len * 4 + pad_delta); | |
636 memmove(addr_at(bci + 1 + new_pad + len*4 + pad_delta), | |
637 _overwrite, -pad_delta); | |
638 } else { | |
639 assert(pad_delta > 0, "check"); | |
640 // Move the expanded instruction up. | |
641 memmove(addr_at(bci +1 + new_pad), | |
642 addr_at(bci +1 + old_pad), | |
643 len * 4); | |
644 } | |
645 } | |
646 return true; | |
647 } |