Mercurial > hg > graal-compiler
annotate src/share/vm/runtime/relocator.cpp @ 2607:008adfd6d850
Fixed the stateBefore of invokes and monitorenter instructions to include the arguments of the instruction.
This is necessary to ensure correct continuation in the interpreter when the stateBefore is used as a deoptimization point.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Fri, 06 May 2011 17:47:17 +0200 |
parents | f95d63e2154a |
children | 8150fa46d2ed |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 1997, 2010, 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 | |
1972 | 25 #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" | |
0 | 33 |
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 // | |
42 class 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 | |
63 class 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 | |
80 class 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 | |
105 class 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 | |
127 Relocator::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. | |
144 methodHandle 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 | |
175 bool 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 | |
199 bool 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 | |
212 int 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. | |
250 int 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. | |
268 void 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". | |
281 void 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" | |
306 void 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". | |
394 void Relocator::adjust_exception_table(int bci, int delta) { | |
395 typeArrayOop table = method()->exception_table(); | |
396 for (int index = 0; index < table->length(); index +=4) { | |
397 if (table->int_at(index) > bci) { | |
398 table->int_at_put(index+0, table->int_at(index+0) + delta); | |
399 table->int_at_put(index+1, table->int_at(index+1) + delta); | |
400 } else if (bci < table->int_at(index+1)) { | |
401 table->int_at_put(index+1, table->int_at(index+1) + delta); | |
402 } | |
403 if (table->int_at(index+2) > bci) | |
404 table->int_at_put(index+2, table->int_at(index+2) + delta); | |
405 } | |
406 } | |
407 | |
408 | |
409 // The width of instruction at "bci" is changing by "delta". Adjust the line number table. | |
410 void 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. | |
426 void 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 | |
1877
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
444 // Create a new array, copying the src array but adding a hole at |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
445 // the specified location |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
446 static typeArrayOop insert_hole_at( |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
447 size_t where, int hole_sz, typeArrayOop src) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
448 Thread* THREAD = Thread::current(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
449 Handle src_hnd(THREAD, src); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
450 typeArrayOop dst = |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
451 oopFactory::new_permanent_byteArray(src->length() + hole_sz, CHECK_NULL); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
452 src = (typeArrayOop)src_hnd(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
453 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
454 address src_addr = (address)src->byte_at_addr(0); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
455 address dst_addr = (address)dst->byte_at_addr(0); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
456 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
457 memcpy(dst_addr, src_addr, where); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
458 memcpy(dst_addr + where + hole_sz, |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
459 src_addr + where, src->length() - where); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
460 return dst; |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
461 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
462 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
463 // The width of instruction at "bci" is changing by "delta". Adjust the stack |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
464 // map frames. |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
465 void Relocator::adjust_stack_map_table(int bci, int delta) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
466 if (method()->has_stackmap_table()) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
467 typeArrayOop data = method()->stackmap_data(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
468 // The data in the array is a classfile representation of the stackmap |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
469 // table attribute, less the initial u2 tag and u4 attribute_length fields. |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
470 stack_map_table_attribute* attr = stack_map_table_attribute::at( |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
471 (address)data->byte_at_addr(0) - (sizeof(u2) + sizeof(u4))); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
472 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
473 int count = attr->number_of_entries(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
474 stack_map_frame* frame = attr->entries(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
475 int bci_iter = -1; |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
476 bool offset_adjusted = false; // only need to adjust one offset |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
477 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
478 for (int i = 0; i < count; ++i) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
479 int offset_delta = frame->offset_delta(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
480 bci_iter += offset_delta; |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
481 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
482 if (!offset_adjusted && bci_iter > bci) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
483 int new_offset_delta = offset_delta + delta; |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
484 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
485 if (frame->is_valid_offset(new_offset_delta)) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
486 frame->set_offset_delta(new_offset_delta); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
487 } else { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
488 assert(frame->is_same_frame() || |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
489 frame->is_same_frame_1_stack_item_frame(), |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
490 "Frame must be one of the compressed forms"); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
491 // The new delta exceeds the capacity of the 'same_frame' or |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
492 // 'same_frame_1_stack_item_frame' frame types. We need to |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
493 // convert these frames to the extended versions, but the extended |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
494 // version is bigger and requires more room. So we allocate a |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
495 // new array and copy the data, being sure to leave u2-sized hole |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
496 // right after the 'frame_type' for the new offset field. |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
497 // |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
498 // We can safely ignore the reverse situation as a small delta |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
499 // can still be used in an extended version of the frame. |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
500 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
501 size_t frame_offset = (address)frame - (address)data->byte_at_addr(0); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
502 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
503 data = insert_hole_at(frame_offset + 1, 2, data); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
504 if (data == NULL) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
505 return; // out-of-memory? |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
506 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
507 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
508 address frame_addr = (address)(data->byte_at_addr(0) + frame_offset); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
509 frame = stack_map_frame::at(frame_addr); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
510 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
511 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
512 // Now convert the frames in place |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
513 if (frame->is_same_frame()) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
514 same_frame_extended::create_at(frame_addr, new_offset_delta); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
515 } else { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
516 same_frame_1_stack_item_extended::create_at( |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
517 frame_addr, new_offset_delta, NULL); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
518 // the verification_info_type should already be at the right spot |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
519 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
520 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
521 offset_adjusted = true; // needs to be done only once, since subsequent |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
522 // values are offsets from the current |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
523 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
524 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
525 // The stack map frame may contain verification types, if so we need to |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
526 // check and update any Uninitialized type's bci (no matter where it is). |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
527 int number_of_types = frame->number_of_types(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
528 verification_type_info* types = frame->types(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
529 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
530 for (int i = 0; i < number_of_types; ++i) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
531 if (types->is_uninitialized() && types->bci() > bci) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
532 types->set_bci(types->bci() + delta); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
533 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
534 types = types->next(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
535 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
536 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
537 // Full frame has stack values too |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
538 full_frame* ff = frame->as_full_frame(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
539 if (ff != NULL) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
540 address eol = (address)types; |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
541 number_of_types = ff->stack_slots(eol); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
542 types = ff->stack(eol); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
543 for (int i = 0; i < number_of_types; ++i) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
544 if (types->is_uninitialized() && types->bci() > bci) { |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
545 types->set_bci(types->bci() + delta); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
546 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
547 types = types->next(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
548 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
549 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
550 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
551 frame = frame->next(); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
552 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
553 |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
554 method()->set_stackmap_data(data); // in case it has changed |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
555 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
556 } |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
557 |
0 | 558 |
559 bool 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. | |
591 bool 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 | |
1877
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
622 // Adjust stack maps |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
623 adjust_stack_map_table(bci, delta); |
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
624 |
0 | 625 // 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 | |
638 bool 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 | |
652 bool 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 | |
730 bool 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); | |
1877
a4c7fe54bf3f
6991315: RedefineClasses fails with java.lang.VerifyError
kamg
parents:
1552
diff
changeset
|
767 memset(addr_at(bci + 1), 0, new_pad); // pad must be 0 |
0 | 768 } |
769 } | |
770 return true; | |
771 } |