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