Mercurial > hg > truffle
annotate src/share/vm/oops/generateOopMap.cpp @ 3762:5c0a3c1858b1
7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
Summary: The LNC array is sized before the start of a scavenge, while the heap may expand during a scavenge. With CMS, the last block of an arbitrary suffice of the LNC array may expand due to coalition with the expansion delta. We now take care not to attempt access past the end of the LNC array. LNC array code will be cleaned up and suitably encapsulated as part of the forthcoming performance RFE 7043675.
Reviewed-by: brutisso
author | ysr |
---|---|
date | Thu, 02 Jun 2011 10:23:36 -0700 |
parents | 3582bf76420e |
children | 540930dc854d 6a991dcb52bb |
rev | line source |
---|---|
0 | 1 /* |
2142 | 2 * Copyright (c) 1997, 2011, 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:
1489
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1489
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:
1489
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "interpreter/bytecodeStream.hpp" | |
27 #include "oops/generateOopMap.hpp" | |
28 #include "oops/oop.inline.hpp" | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
29 #include "oops/symbol.hpp" |
1972 | 30 #include "runtime/handles.inline.hpp" |
31 #include "runtime/java.hpp" | |
32 #include "runtime/relocator.hpp" | |
33 #include "utilities/bitMap.inline.hpp" | |
34 | |
0 | 35 // |
36 // | |
37 // Compute stack layouts for each instruction in method. | |
38 // | |
39 // Problems: | |
40 // - What to do about jsr with different types of local vars? | |
41 // Need maps that are conditional on jsr path? | |
42 // - Jsr and exceptions should be done more efficiently (the retAddr stuff) | |
43 // | |
44 // Alternative: | |
45 // - Could extend verifier to provide this information. | |
46 // For: one fewer abstract interpreter to maintain. Against: the verifier | |
47 // solves a bigger problem so slower (undesirable to force verification of | |
48 // everything?). | |
49 // | |
50 // Algorithm: | |
51 // Partition bytecodes into basic blocks | |
52 // For each basic block: store entry state (vars, stack). For instructions | |
53 // inside basic blocks we do not store any state (instead we recompute it | |
54 // from state produced by previous instruction). | |
55 // | |
56 // Perform abstract interpretation of bytecodes over this lattice: | |
57 // | |
58 // _--'#'--_ | |
59 // / / \ \ | |
60 // / / \ \ | |
61 // / | | \ | |
62 // 'r' 'v' 'p' ' ' | |
63 // \ | | / | |
64 // \ \ / / | |
65 // \ \ / / | |
66 // -- '@' -- | |
67 // | |
68 // '#' top, result of conflict merge | |
69 // 'r' reference type | |
70 // 'v' value type | |
71 // 'p' pc type for jsr/ret | |
72 // ' ' uninitialized; never occurs on operand stack in Java | |
73 // '@' bottom/unexecuted; initial state each bytecode. | |
74 // | |
75 // Basic block headers are the only merge points. We use this iteration to | |
76 // compute the information: | |
77 // | |
78 // find basic blocks; | |
79 // initialize them with uninitialized state; | |
80 // initialize first BB according to method signature; | |
81 // mark first BB changed | |
82 // while (some BB is changed) do { | |
83 // perform abstract interpration of all bytecodes in BB; | |
84 // merge exit state of BB into entry state of all successor BBs, | |
85 // noting if any of these change; | |
86 // } | |
87 // | |
88 // One additional complication is necessary. The jsr instruction pushes | |
89 // a return PC on the stack (a 'p' type in the abstract interpretation). | |
90 // To be able to process "ret" bytecodes, we keep track of these return | |
91 // PC's in a 'retAddrs' structure in abstract interpreter context (when | |
92 // processing a "ret" bytecodes, it is not sufficient to know that it gets | |
93 // an argument of the right type 'p'; we need to know which address it | |
94 // returns to). | |
95 // | |
96 // (Note this comment is borrowed form the original author of the algorithm) | |
97 | |
98 // ComputeCallStack | |
99 // | |
100 // Specialization of SignatureIterator - compute the effects of a call | |
101 // | |
102 class ComputeCallStack : public SignatureIterator { | |
103 CellTypeState *_effect; | |
104 int _idx; | |
105 | |
106 void setup(); | |
107 void set(CellTypeState state) { _effect[_idx++] = state; } | |
108 int length() { return _idx; }; | |
109 | |
110 virtual void do_bool () { set(CellTypeState::value); }; | |
111 virtual void do_char () { set(CellTypeState::value); }; | |
112 virtual void do_float () { set(CellTypeState::value); }; | |
113 virtual void do_byte () { set(CellTypeState::value); }; | |
114 virtual void do_short () { set(CellTypeState::value); }; | |
115 virtual void do_int () { set(CellTypeState::value); }; | |
116 virtual void do_void () { set(CellTypeState::bottom);}; | |
117 virtual void do_object(int begin, int end) { set(CellTypeState::ref); }; | |
118 virtual void do_array (int begin, int end) { set(CellTypeState::ref); }; | |
119 | |
120 void do_double() { set(CellTypeState::value); | |
121 set(CellTypeState::value); } | |
122 void do_long () { set(CellTypeState::value); | |
123 set(CellTypeState::value); } | |
124 | |
125 public: | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
126 ComputeCallStack(Symbol* signature) : SignatureIterator(signature) {}; |
0 | 127 |
128 // Compute methods | |
129 int compute_for_parameters(bool is_static, CellTypeState *effect) { | |
130 _idx = 0; | |
131 _effect = effect; | |
132 | |
133 if (!is_static) | |
134 effect[_idx++] = CellTypeState::ref; | |
135 | |
136 iterate_parameters(); | |
137 | |
138 return length(); | |
139 }; | |
140 | |
141 int compute_for_returntype(CellTypeState *effect) { | |
142 _idx = 0; | |
143 _effect = effect; | |
144 iterate_returntype(); | |
145 set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works | |
146 | |
147 return length(); | |
148 } | |
149 }; | |
150 | |
151 //========================================================================================= | |
152 // ComputeEntryStack | |
153 // | |
154 // Specialization of SignatureIterator - in order to set up first stack frame | |
155 // | |
156 class ComputeEntryStack : public SignatureIterator { | |
157 CellTypeState *_effect; | |
158 int _idx; | |
159 | |
160 void setup(); | |
161 void set(CellTypeState state) { _effect[_idx++] = state; } | |
162 int length() { return _idx; }; | |
163 | |
164 virtual void do_bool () { set(CellTypeState::value); }; | |
165 virtual void do_char () { set(CellTypeState::value); }; | |
166 virtual void do_float () { set(CellTypeState::value); }; | |
167 virtual void do_byte () { set(CellTypeState::value); }; | |
168 virtual void do_short () { set(CellTypeState::value); }; | |
169 virtual void do_int () { set(CellTypeState::value); }; | |
170 virtual void do_void () { set(CellTypeState::bottom);}; | |
171 virtual void do_object(int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } | |
172 virtual void do_array (int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } | |
173 | |
174 void do_double() { set(CellTypeState::value); | |
175 set(CellTypeState::value); } | |
176 void do_long () { set(CellTypeState::value); | |
177 set(CellTypeState::value); } | |
178 | |
179 public: | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
180 ComputeEntryStack(Symbol* signature) : SignatureIterator(signature) {}; |
0 | 181 |
182 // Compute methods | |
183 int compute_for_parameters(bool is_static, CellTypeState *effect) { | |
184 _idx = 0; | |
185 _effect = effect; | |
186 | |
187 if (!is_static) | |
188 effect[_idx++] = CellTypeState::make_slot_ref(0); | |
189 | |
190 iterate_parameters(); | |
191 | |
192 return length(); | |
193 }; | |
194 | |
195 int compute_for_returntype(CellTypeState *effect) { | |
196 _idx = 0; | |
197 _effect = effect; | |
198 iterate_returntype(); | |
199 set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works | |
200 | |
201 return length(); | |
202 } | |
203 }; | |
204 | |
205 //===================================================================================== | |
206 // | |
207 // Implementation of RetTable/RetTableEntry | |
208 // | |
209 // Contains function to itereate through all bytecodes | |
210 // and find all return entry points | |
211 // | |
212 int RetTable::_init_nof_entries = 10; | |
213 int RetTableEntry::_init_nof_jsrs = 5; | |
214 | |
215 void RetTableEntry::add_delta(int bci, int delta) { | |
216 if (_target_bci > bci) _target_bci += delta; | |
217 | |
218 for (int k = 0; k < _jsrs->length(); k++) { | |
219 int jsr = _jsrs->at(k); | |
220 if (jsr > bci) _jsrs->at_put(k, jsr+delta); | |
221 } | |
222 } | |
223 | |
224 void RetTable::compute_ret_table(methodHandle method) { | |
225 BytecodeStream i(method); | |
226 Bytecodes::Code bytecode; | |
227 | |
228 while( (bytecode = i.next()) >= 0) { | |
229 switch (bytecode) { | |
230 case Bytecodes::_jsr: | |
231 add_jsr(i.next_bci(), i.dest()); | |
232 break; | |
233 case Bytecodes::_jsr_w: | |
234 add_jsr(i.next_bci(), i.dest_w()); | |
235 break; | |
236 } | |
237 } | |
238 } | |
239 | |
240 void RetTable::add_jsr(int return_bci, int target_bci) { | |
241 RetTableEntry* entry = _first; | |
242 | |
243 // Scan table for entry | |
244 for (;entry && entry->target_bci() != target_bci; entry = entry->next()); | |
245 | |
246 if (!entry) { | |
247 // Allocate new entry and put in list | |
248 entry = new RetTableEntry(target_bci, _first); | |
249 _first = entry; | |
250 } | |
251 | |
252 // Now "entry" is set. Make sure that the entry is initialized | |
253 // and has room for the new jsr. | |
254 entry->add_jsr(return_bci); | |
255 } | |
256 | |
257 RetTableEntry* RetTable::find_jsrs_for_target(int targBci) { | |
258 RetTableEntry *cur = _first; | |
259 | |
260 while(cur) { | |
261 assert(cur->target_bci() != -1, "sanity check"); | |
262 if (cur->target_bci() == targBci) return cur; | |
263 cur = cur->next(); | |
264 } | |
265 ShouldNotReachHere(); | |
266 return NULL; | |
267 } | |
268 | |
269 // The instruction at bci is changing size by "delta". Update the return map. | |
270 void RetTable::update_ret_table(int bci, int delta) { | |
271 RetTableEntry *cur = _first; | |
272 while(cur) { | |
273 cur->add_delta(bci, delta); | |
274 cur = cur->next(); | |
275 } | |
276 } | |
277 | |
278 // | |
279 // Celltype state | |
280 // | |
281 | |
282 CellTypeState CellTypeState::bottom = CellTypeState::make_bottom(); | |
283 CellTypeState CellTypeState::uninit = CellTypeState::make_any(uninit_value); | |
284 CellTypeState CellTypeState::ref = CellTypeState::make_any(ref_conflict); | |
285 CellTypeState CellTypeState::value = CellTypeState::make_any(val_value); | |
286 CellTypeState CellTypeState::refUninit = CellTypeState::make_any(ref_conflict | uninit_value); | |
287 CellTypeState CellTypeState::top = CellTypeState::make_top(); | |
288 CellTypeState CellTypeState::addr = CellTypeState::make_any(addr_conflict); | |
289 | |
290 // Commonly used constants | |
291 static CellTypeState epsilonCTS[1] = { CellTypeState::bottom }; | |
292 static CellTypeState refCTS = CellTypeState::ref; | |
293 static CellTypeState valCTS = CellTypeState::value; | |
294 static CellTypeState vCTS[2] = { CellTypeState::value, CellTypeState::bottom }; | |
295 static CellTypeState rCTS[2] = { CellTypeState::ref, CellTypeState::bottom }; | |
296 static CellTypeState rrCTS[3] = { CellTypeState::ref, CellTypeState::ref, CellTypeState::bottom }; | |
297 static CellTypeState vrCTS[3] = { CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; | |
298 static CellTypeState vvCTS[3] = { CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; | |
299 static CellTypeState rvrCTS[4] = { CellTypeState::ref, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; | |
300 static CellTypeState vvrCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; | |
301 static CellTypeState vvvCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; | |
302 static CellTypeState vvvrCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; | |
303 static CellTypeState vvvvCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; | |
304 | |
305 char CellTypeState::to_char() const { | |
306 if (can_be_reference()) { | |
307 if (can_be_value() || can_be_address()) | |
308 return '#'; // Conflict that needs to be rewritten | |
309 else | |
310 return 'r'; | |
311 } else if (can_be_value()) | |
312 return 'v'; | |
313 else if (can_be_address()) | |
314 return 'p'; | |
315 else if (can_be_uninit()) | |
316 return ' '; | |
317 else | |
318 return '@'; | |
319 } | |
320 | |
321 | |
322 // Print a detailed CellTypeState. Indicate all bits that are set. If | |
323 // the CellTypeState represents an address or a reference, print the | |
324 // value of the additional information. | |
325 void CellTypeState::print(outputStream *os) { | |
326 if (can_be_address()) { | |
327 os->print("(p"); | |
328 } else { | |
329 os->print("( "); | |
330 } | |
331 if (can_be_reference()) { | |
332 os->print("r"); | |
333 } else { | |
334 os->print(" "); | |
335 } | |
336 if (can_be_value()) { | |
337 os->print("v"); | |
338 } else { | |
339 os->print(" "); | |
340 } | |
341 if (can_be_uninit()) { | |
342 os->print("u|"); | |
343 } else { | |
344 os->print(" |"); | |
345 } | |
346 if (is_info_top()) { | |
347 os->print("Top)"); | |
348 } else if (is_info_bottom()) { | |
349 os->print("Bot)"); | |
350 } else { | |
351 if (is_reference()) { | |
352 int info = get_info(); | |
353 int data = info & ~(ref_not_lock_bit | ref_slot_bit); | |
354 if (info & ref_not_lock_bit) { | |
355 // Not a monitor lock reference. | |
356 if (info & ref_slot_bit) { | |
357 // slot | |
358 os->print("slot%d)", data); | |
359 } else { | |
360 // line | |
361 os->print("line%d)", data); | |
362 } | |
363 } else { | |
364 // lock | |
365 os->print("lock%d)", data); | |
366 } | |
367 } else { | |
368 os->print("%d)", get_info()); | |
369 } | |
370 } | |
371 } | |
372 | |
373 // | |
374 // Basicblock handling methods | |
375 // | |
376 | |
377 void GenerateOopMap ::initialize_bb() { | |
378 _gc_points = 0; | |
379 _bb_count = 0; | |
342 | 380 _bb_hdr_bits.clear(); |
381 _bb_hdr_bits.resize(method()->code_size()); | |
0 | 382 } |
383 | |
384 void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) { | |
385 assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds"); | |
386 if (c->is_bb_header(bci)) | |
387 return; | |
388 | |
389 if (TraceNewOopMapGeneration) { | |
390 tty->print_cr("Basicblock#%d begins at: %d", c->_bb_count, bci); | |
391 } | |
392 c->set_bbmark_bit(bci); | |
393 c->_bb_count++; | |
394 } | |
395 | |
396 | |
397 void GenerateOopMap::mark_bbheaders_and_count_gc_points() { | |
398 initialize_bb(); | |
399 | |
400 bool fellThrough = false; // False to get first BB marked. | |
401 | |
402 // First mark all exception handlers as start of a basic-block | |
403 typeArrayOop excps = method()->exception_table(); | |
404 for(int i = 0; i < excps->length(); i += 4) { | |
405 int handler_pc_idx = i+2; | |
406 bb_mark_fct(this, excps->int_at(handler_pc_idx), NULL); | |
407 } | |
408 | |
409 // Then iterate through the code | |
410 BytecodeStream bcs(_method); | |
411 Bytecodes::Code bytecode; | |
412 | |
413 while( (bytecode = bcs.next()) >= 0) { | |
414 int bci = bcs.bci(); | |
415 | |
416 if (!fellThrough) | |
417 bb_mark_fct(this, bci, NULL); | |
418 | |
419 fellThrough = jump_targets_do(&bcs, &GenerateOopMap::bb_mark_fct, NULL); | |
420 | |
421 /* We will also mark successors of jsr's as basic block headers. */ | |
422 switch (bytecode) { | |
423 case Bytecodes::_jsr: | |
424 assert(!fellThrough, "should not happen"); | |
425 bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL); | |
426 break; | |
427 case Bytecodes::_jsr_w: | |
428 assert(!fellThrough, "should not happen"); | |
429 bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL); | |
430 break; | |
431 } | |
432 | |
433 if (possible_gc_point(&bcs)) | |
434 _gc_points++; | |
435 } | |
436 } | |
437 | |
438 void GenerateOopMap::reachable_basicblock(GenerateOopMap *c, int bci, int *data) { | |
439 assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds"); | |
440 BasicBlock* bb = c->get_basic_block_at(bci); | |
441 if (bb->is_dead()) { | |
442 bb->mark_as_alive(); | |
443 *data = 1; // Mark basicblock as changed | |
444 } | |
445 } | |
446 | |
447 | |
448 void GenerateOopMap::mark_reachable_code() { | |
449 int change = 1; // int to get function pointers to work | |
450 | |
451 // Mark entry basic block as alive and all exception handlers | |
452 _basic_blocks[0].mark_as_alive(); | |
453 typeArrayOop excps = method()->exception_table(); | |
454 for(int i = 0; i < excps->length(); i += 4) { | |
455 int handler_pc_idx = i+2; | |
456 BasicBlock *bb = get_basic_block_at(excps->int_at(handler_pc_idx)); | |
457 // If block is not already alive (due to multiple exception handlers to same bb), then | |
458 // make it alive | |
459 if (bb->is_dead()) bb->mark_as_alive(); | |
460 } | |
461 | |
462 BytecodeStream bcs(_method); | |
463 | |
464 // Iterate through all basic blocks until we reach a fixpoint | |
465 while (change) { | |
466 change = 0; | |
467 | |
468 for (int i = 0; i < _bb_count; i++) { | |
469 BasicBlock *bb = &_basic_blocks[i]; | |
470 if (bb->is_alive()) { | |
471 // Position bytecodestream at last bytecode in basicblock | |
472 bcs.set_start(bb->_end_bci); | |
473 bcs.next(); | |
474 Bytecodes::Code bytecode = bcs.code(); | |
475 int bci = bcs.bci(); | |
476 assert(bci == bb->_end_bci, "wrong bci"); | |
477 | |
478 bool fell_through = jump_targets_do(&bcs, &GenerateOopMap::reachable_basicblock, &change); | |
479 | |
480 // We will also mark successors of jsr's as alive. | |
481 switch (bytecode) { | |
482 case Bytecodes::_jsr: | |
483 case Bytecodes::_jsr_w: | |
484 assert(!fell_through, "should not happen"); | |
485 reachable_basicblock(this, bci + Bytecodes::length_for(bytecode), &change); | |
486 break; | |
487 } | |
488 if (fell_through) { | |
489 // Mark successor as alive | |
490 if (bb[1].is_dead()) { | |
491 bb[1].mark_as_alive(); | |
492 change = 1; | |
493 } | |
494 } | |
495 } | |
496 } | |
497 } | |
498 } | |
499 | |
500 /* If the current instruction in "c" has no effect on control flow, | |
501 returns "true". Otherwise, calls "jmpFct" one or more times, with | |
502 "c", an appropriate "pcDelta", and "data" as arguments, then | |
503 returns "false". There is one exception: if the current | |
504 instruction is a "ret", returns "false" without calling "jmpFct". | |
505 Arrangements for tracking the control flow of a "ret" must be made | |
506 externally. */ | |
507 bool GenerateOopMap::jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int *data) { | |
508 int bci = bcs->bci(); | |
509 | |
510 switch (bcs->code()) { | |
511 case Bytecodes::_ifeq: | |
512 case Bytecodes::_ifne: | |
513 case Bytecodes::_iflt: | |
514 case Bytecodes::_ifge: | |
515 case Bytecodes::_ifgt: | |
516 case Bytecodes::_ifle: | |
517 case Bytecodes::_if_icmpeq: | |
518 case Bytecodes::_if_icmpne: | |
519 case Bytecodes::_if_icmplt: | |
520 case Bytecodes::_if_icmpge: | |
521 case Bytecodes::_if_icmpgt: | |
522 case Bytecodes::_if_icmple: | |
523 case Bytecodes::_if_acmpeq: | |
524 case Bytecodes::_if_acmpne: | |
525 case Bytecodes::_ifnull: | |
526 case Bytecodes::_ifnonnull: | |
527 (*jmpFct)(this, bcs->dest(), data); | |
528 (*jmpFct)(this, bci + 3, data); | |
529 break; | |
530 | |
531 case Bytecodes::_goto: | |
532 (*jmpFct)(this, bcs->dest(), data); | |
533 break; | |
534 case Bytecodes::_goto_w: | |
535 (*jmpFct)(this, bcs->dest_w(), data); | |
536 break; | |
537 case Bytecodes::_tableswitch: | |
2142 | 538 { Bytecode_tableswitch tableswitch(method(), bcs->bcp()); |
539 int len = tableswitch.length(); | |
0 | 540 |
2142 | 541 (*jmpFct)(this, bci + tableswitch.default_offset(), data); /* Default. jump address */ |
0 | 542 while (--len >= 0) { |
2142 | 543 (*jmpFct)(this, bci + tableswitch.dest_offset_at(len), data); |
0 | 544 } |
545 break; | |
546 } | |
547 | |
548 case Bytecodes::_lookupswitch: | |
2142 | 549 { Bytecode_lookupswitch lookupswitch(method(), bcs->bcp()); |
550 int npairs = lookupswitch.number_of_pairs(); | |
551 (*jmpFct)(this, bci + lookupswitch.default_offset(), data); /* Default. */ | |
0 | 552 while(--npairs >= 0) { |
2142 | 553 LookupswitchPair pair = lookupswitch.pair_at(npairs); |
554 (*jmpFct)(this, bci + pair.offset(), data); | |
0 | 555 } |
556 break; | |
557 } | |
558 case Bytecodes::_jsr: | |
559 assert(bcs->is_wide()==false, "sanity check"); | |
560 (*jmpFct)(this, bcs->dest(), data); | |
561 | |
562 | |
563 | |
564 break; | |
565 case Bytecodes::_jsr_w: | |
566 (*jmpFct)(this, bcs->dest_w(), data); | |
567 break; | |
568 case Bytecodes::_wide: | |
569 ShouldNotReachHere(); | |
570 return true; | |
571 break; | |
572 case Bytecodes::_athrow: | |
573 case Bytecodes::_ireturn: | |
574 case Bytecodes::_lreturn: | |
575 case Bytecodes::_freturn: | |
576 case Bytecodes::_dreturn: | |
577 case Bytecodes::_areturn: | |
578 case Bytecodes::_return: | |
579 case Bytecodes::_ret: | |
580 break; | |
581 default: | |
582 return true; | |
583 } | |
584 return false; | |
585 } | |
586 | |
587 /* Requires "pc" to be the head of a basic block; returns that basic | |
588 block. */ | |
589 BasicBlock *GenerateOopMap::get_basic_block_at(int bci) const { | |
590 BasicBlock* bb = get_basic_block_containing(bci); | |
591 assert(bb->_bci == bci, "should have found BB"); | |
592 return bb; | |
593 } | |
594 | |
595 // Requires "pc" to be the start of an instruction; returns the basic | |
596 // block containing that instruction. */ | |
597 BasicBlock *GenerateOopMap::get_basic_block_containing(int bci) const { | |
598 BasicBlock *bbs = _basic_blocks; | |
599 int lo = 0, hi = _bb_count - 1; | |
600 | |
601 while (lo <= hi) { | |
602 int m = (lo + hi) / 2; | |
603 int mbci = bbs[m]._bci; | |
604 int nbci; | |
605 | |
606 if ( m == _bb_count-1) { | |
607 assert( bci >= mbci && bci < method()->code_size(), "sanity check failed"); | |
608 return bbs+m; | |
609 } else { | |
610 nbci = bbs[m+1]._bci; | |
611 } | |
612 | |
613 if ( mbci <= bci && bci < nbci) { | |
614 return bbs+m; | |
615 } else if (mbci < bci) { | |
616 lo = m + 1; | |
617 } else { | |
618 assert(mbci > bci, "sanity check"); | |
619 hi = m - 1; | |
620 } | |
621 } | |
622 | |
623 fatal("should have found BB"); | |
624 return NULL; | |
625 } | |
626 | |
627 void GenerateOopMap::restore_state(BasicBlock *bb) | |
628 { | |
629 memcpy(_state, bb->_state, _state_len*sizeof(CellTypeState)); | |
630 _stack_top = bb->_stack_top; | |
631 _monitor_top = bb->_monitor_top; | |
632 } | |
633 | |
634 int GenerateOopMap::next_bb_start_pc(BasicBlock *bb) { | |
635 int bbNum = bb - _basic_blocks + 1; | |
636 if (bbNum == _bb_count) | |
637 return method()->code_size(); | |
638 | |
639 return _basic_blocks[bbNum]._bci; | |
640 } | |
641 | |
642 // | |
643 // CellType handling methods | |
644 // | |
645 | |
646 void GenerateOopMap::init_state() { | |
647 _state_len = _max_locals + _max_stack + _max_monitors; | |
648 _state = NEW_RESOURCE_ARRAY(CellTypeState, _state_len); | |
649 memset(_state, 0, _state_len * sizeof(CellTypeState)); | |
650 _state_vec_buf = NEW_RESOURCE_ARRAY(char, MAX3(_max_locals, _max_stack, _max_monitors) + 1/*for null terminator char */); | |
651 } | |
652 | |
653 void GenerateOopMap::make_context_uninitialized() { | |
654 CellTypeState* vs = vars(); | |
655 | |
656 for (int i = 0; i < _max_locals; i++) | |
657 vs[i] = CellTypeState::uninit; | |
658 | |
659 _stack_top = 0; | |
660 _monitor_top = 0; | |
661 } | |
662 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
663 int GenerateOopMap::methodsig_to_effect(Symbol* signature, bool is_static, CellTypeState* effect) { |
0 | 664 ComputeEntryStack ces(signature); |
665 return ces.compute_for_parameters(is_static, effect); | |
666 } | |
667 | |
668 // Return result of merging cts1 and cts2. | |
669 CellTypeState CellTypeState::merge(CellTypeState cts, int slot) const { | |
670 CellTypeState result; | |
671 | |
672 assert(!is_bottom() && !cts.is_bottom(), | |
673 "merge of bottom values is handled elsewhere"); | |
674 | |
675 result._state = _state | cts._state; | |
676 | |
677 // If the top bit is set, we don't need to do any more work. | |
678 if (!result.is_info_top()) { | |
679 assert((result.can_be_address() || result.can_be_reference()), | |
680 "only addresses and references have non-top info"); | |
681 | |
682 if (!equal(cts)) { | |
683 // The two values being merged are different. Raise to top. | |
684 if (result.is_reference()) { | |
685 result = CellTypeState::make_slot_ref(slot); | |
686 } else { | |
687 result._state |= info_conflict; | |
688 } | |
689 } | |
690 } | |
691 assert(result.is_valid_state(), "checking that CTS merge maintains legal state"); | |
692 | |
693 return result; | |
694 } | |
695 | |
696 // Merge the variable state for locals and stack from cts into bbts. | |
697 bool GenerateOopMap::merge_local_state_vectors(CellTypeState* cts, | |
698 CellTypeState* bbts) { | |
699 int i; | |
700 int len = _max_locals + _stack_top; | |
701 bool change = false; | |
702 | |
703 for (i = len - 1; i >= 0; i--) { | |
704 CellTypeState v = cts[i].merge(bbts[i], i); | |
705 change = change || !v.equal(bbts[i]); | |
706 bbts[i] = v; | |
707 } | |
708 | |
709 return change; | |
710 } | |
711 | |
712 // Merge the monitor stack state from cts into bbts. | |
713 bool GenerateOopMap::merge_monitor_state_vectors(CellTypeState* cts, | |
714 CellTypeState* bbts) { | |
715 bool change = false; | |
716 if (_max_monitors > 0 && _monitor_top != bad_monitors) { | |
717 // If there are no monitors in the program, or there has been | |
718 // a monitor matching error before this point in the program, | |
719 // then we do not merge in the monitor state. | |
720 | |
721 int base = _max_locals + _max_stack; | |
722 int len = base + _monitor_top; | |
723 for (int i = len - 1; i >= base; i--) { | |
724 CellTypeState v = cts[i].merge(bbts[i], i); | |
725 | |
726 // Can we prove that, when there has been a change, it will already | |
727 // have been detected at this point? That would make this equal | |
728 // check here unnecessary. | |
729 change = change || !v.equal(bbts[i]); | |
730 bbts[i] = v; | |
731 } | |
732 } | |
733 | |
734 return change; | |
735 } | |
736 | |
737 void GenerateOopMap::copy_state(CellTypeState *dst, CellTypeState *src) { | |
738 int len = _max_locals + _stack_top; | |
739 for (int i = 0; i < len; i++) { | |
740 if (src[i].is_nonlock_reference()) { | |
741 dst[i] = CellTypeState::make_slot_ref(i); | |
742 } else { | |
743 dst[i] = src[i]; | |
744 } | |
745 } | |
746 if (_max_monitors > 0 && _monitor_top != bad_monitors) { | |
747 int base = _max_locals + _max_stack; | |
748 len = base + _monitor_top; | |
749 for (int i = base; i < len; i++) { | |
750 dst[i] = src[i]; | |
751 } | |
752 } | |
753 } | |
754 | |
755 | |
756 // Merge the states for the current block and the next. As long as a | |
757 // block is reachable the locals and stack must be merged. If the | |
758 // stack heights don't match then this is a verification error and | |
759 // it's impossible to interpret the code. Simultaneously monitor | |
760 // states are being check to see if they nest statically. If monitor | |
761 // depths match up then their states are merged. Otherwise the | |
762 // mismatch is simply recorded and interpretation continues since | |
763 // monitor matching is purely informational and doesn't say anything | |
764 // about the correctness of the code. | |
765 void GenerateOopMap::merge_state_into_bb(BasicBlock *bb) { | |
766 assert(bb->is_alive(), "merging state into a dead basicblock"); | |
767 | |
768 if (_stack_top == bb->_stack_top) { | |
769 // always merge local state even if monitors don't match. | |
770 if (merge_local_state_vectors(_state, bb->_state)) { | |
771 bb->set_changed(true); | |
772 } | |
773 if (_monitor_top == bb->_monitor_top) { | |
774 // monitors still match so continue merging monitor states. | |
775 if (merge_monitor_state_vectors(_state, bb->_state)) { | |
776 bb->set_changed(true); | |
777 } | |
778 } else { | |
779 if (TraceMonitorMismatch) { | |
780 report_monitor_mismatch("monitor stack height merge conflict"); | |
781 } | |
782 // When the monitor stacks are not matched, we set _monitor_top to | |
783 // bad_monitors. This signals that, from here on, the monitor stack cannot | |
784 // be trusted. In particular, monitorexit bytecodes may throw | |
785 // exceptions. We mark this block as changed so that the change | |
786 // propagates properly. | |
787 bb->_monitor_top = bad_monitors; | |
788 bb->set_changed(true); | |
789 _monitor_safe = false; | |
790 } | |
791 } else if (!bb->is_reachable()) { | |
792 // First time we look at this BB | |
793 copy_state(bb->_state, _state); | |
794 bb->_stack_top = _stack_top; | |
795 bb->_monitor_top = _monitor_top; | |
796 bb->set_changed(true); | |
797 } else { | |
798 verify_error("stack height conflict: %d vs. %d", _stack_top, bb->_stack_top); | |
799 } | |
800 } | |
801 | |
802 void GenerateOopMap::merge_state(GenerateOopMap *gom, int bci, int* data) { | |
803 gom->merge_state_into_bb(gom->get_basic_block_at(bci)); | |
804 } | |
805 | |
806 void GenerateOopMap::set_var(int localNo, CellTypeState cts) { | |
807 assert(cts.is_reference() || cts.is_value() || cts.is_address(), | |
808 "wrong celltypestate"); | |
809 if (localNo < 0 || localNo > _max_locals) { | |
810 verify_error("variable write error: r%d", localNo); | |
811 return; | |
812 } | |
813 vars()[localNo] = cts; | |
814 } | |
815 | |
816 CellTypeState GenerateOopMap::get_var(int localNo) { | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1138
diff
changeset
|
817 assert(localNo < _max_locals + _nof_refval_conflicts, "variable read error"); |
0 | 818 if (localNo < 0 || localNo > _max_locals) { |
819 verify_error("variable read error: r%d", localNo); | |
820 return valCTS; // just to pick something; | |
821 } | |
822 return vars()[localNo]; | |
823 } | |
824 | |
825 CellTypeState GenerateOopMap::pop() { | |
826 if ( _stack_top <= 0) { | |
827 verify_error("stack underflow"); | |
828 return valCTS; // just to pick something | |
829 } | |
830 return stack()[--_stack_top]; | |
831 } | |
832 | |
833 void GenerateOopMap::push(CellTypeState cts) { | |
834 if ( _stack_top >= _max_stack) { | |
835 verify_error("stack overflow"); | |
836 return; | |
837 } | |
838 stack()[_stack_top++] = cts; | |
839 } | |
840 | |
841 CellTypeState GenerateOopMap::monitor_pop() { | |
842 assert(_monitor_top != bad_monitors, "monitor_pop called on error monitor stack"); | |
843 if (_monitor_top == 0) { | |
844 // We have detected a pop of an empty monitor stack. | |
845 _monitor_safe = false; | |
846 _monitor_top = bad_monitors; | |
847 | |
848 if (TraceMonitorMismatch) { | |
849 report_monitor_mismatch("monitor stack underflow"); | |
850 } | |
851 return CellTypeState::ref; // just to keep the analysis going. | |
852 } | |
853 return monitors()[--_monitor_top]; | |
854 } | |
855 | |
856 void GenerateOopMap::monitor_push(CellTypeState cts) { | |
857 assert(_monitor_top != bad_monitors, "monitor_push called on error monitor stack"); | |
858 if (_monitor_top >= _max_monitors) { | |
859 // Some monitorenter is being executed more than once. | |
860 // This means that the monitor stack cannot be simulated. | |
861 _monitor_safe = false; | |
862 _monitor_top = bad_monitors; | |
863 | |
864 if (TraceMonitorMismatch) { | |
865 report_monitor_mismatch("monitor stack overflow"); | |
866 } | |
867 return; | |
868 } | |
869 monitors()[_monitor_top++] = cts; | |
870 } | |
871 | |
872 // | |
873 // Interpretation handling methods | |
874 // | |
875 | |
876 void GenerateOopMap::do_interpretation() | |
877 { | |
878 // "i" is just for debugging, so we can detect cases where this loop is | |
879 // iterated more than once. | |
880 int i = 0; | |
881 do { | |
882 #ifndef PRODUCT | |
883 if (TraceNewOopMapGeneration) { | |
884 tty->print("\n\nIteration #%d of do_interpretation loop, method:\n", i); | |
885 method()->print_name(tty); | |
886 tty->print("\n\n"); | |
887 } | |
888 #endif | |
889 _conflict = false; | |
890 _monitor_safe = true; | |
891 // init_state is now called from init_basic_blocks. The length of a | |
892 // state vector cannot be determined until we have made a pass through | |
893 // the bytecodes counting the possible monitor entries. | |
894 if (!_got_error) init_basic_blocks(); | |
895 if (!_got_error) setup_method_entry_state(); | |
896 if (!_got_error) interp_all(); | |
897 if (!_got_error) rewrite_refval_conflicts(); | |
898 i++; | |
899 } while (_conflict && !_got_error); | |
900 } | |
901 | |
902 void GenerateOopMap::init_basic_blocks() { | |
903 // Note: Could consider reserving only the needed space for each BB's state | |
904 // (entry stack may not be of maximal height for every basic block). | |
905 // But cumbersome since we don't know the stack heights yet. (Nor the | |
906 // monitor stack heights...) | |
907 | |
908 _basic_blocks = NEW_RESOURCE_ARRAY(BasicBlock, _bb_count); | |
909 | |
910 // Make a pass through the bytecodes. Count the number of monitorenters. | |
911 // This can be used an upper bound on the monitor stack depth in programs | |
912 // which obey stack discipline with their monitor usage. Initialize the | |
913 // known information about basic blocks. | |
914 BytecodeStream j(_method); | |
915 Bytecodes::Code bytecode; | |
916 | |
917 int bbNo = 0; | |
918 int monitor_count = 0; | |
919 int prev_bci = -1; | |
920 while( (bytecode = j.next()) >= 0) { | |
921 if (j.code() == Bytecodes::_monitorenter) { | |
922 monitor_count++; | |
923 } | |
924 | |
925 int bci = j.bci(); | |
926 if (is_bb_header(bci)) { | |
927 // Initialize the basicblock structure | |
928 BasicBlock *bb = _basic_blocks + bbNo; | |
929 bb->_bci = bci; | |
930 bb->_max_locals = _max_locals; | |
931 bb->_max_stack = _max_stack; | |
932 bb->set_changed(false); | |
933 bb->_stack_top = BasicBlock::_dead_basic_block; // Initialize all basicblocks are dead. | |
934 bb->_monitor_top = bad_monitors; | |
935 | |
936 if (bbNo > 0) { | |
937 _basic_blocks[bbNo - 1]._end_bci = prev_bci; | |
938 } | |
939 | |
940 bbNo++; | |
941 } | |
942 // Remember prevous bci. | |
943 prev_bci = bci; | |
944 } | |
945 // Set | |
946 _basic_blocks[bbNo-1]._end_bci = prev_bci; | |
947 | |
948 | |
342 | 949 // Check that the correct number of basicblocks was found |
950 if (bbNo !=_bb_count) { | |
951 if (bbNo < _bb_count) { | |
952 verify_error("jump into the middle of instruction?"); | |
953 return; | |
954 } else { | |
955 verify_error("extra basic blocks - should not happen?"); | |
956 return; | |
957 } | |
958 } | |
959 | |
0 | 960 _max_monitors = monitor_count; |
961 | |
962 // Now that we have a bound on the depth of the monitor stack, we can | |
963 // initialize the CellTypeState-related information. | |
964 init_state(); | |
965 | |
966 // We allocate space for all state-vectors for all basicblocks in one huge chuck. | |
967 // Then in the next part of the code, we set a pointer in each _basic_block that | |
968 // points to each piece. | |
969 CellTypeState *basicBlockState = NEW_RESOURCE_ARRAY(CellTypeState, bbNo * _state_len); | |
970 memset(basicBlockState, 0, bbNo * _state_len * sizeof(CellTypeState)); | |
971 | |
972 // Make a pass over the basicblocks and assign their state vectors. | |
973 for (int blockNum=0; blockNum < bbNo; blockNum++) { | |
974 BasicBlock *bb = _basic_blocks + blockNum; | |
975 bb->_state = basicBlockState + blockNum * _state_len; | |
976 | |
977 #ifdef ASSERT | |
978 if (blockNum + 1 < bbNo) { | |
979 address bcp = _method->bcp_from(bb->_end_bci); | |
2142 | 980 int bc_len = Bytecodes::java_length_at(_method(), bcp); |
0 | 981 assert(bb->_end_bci + bc_len == bb[1]._bci, "unmatched bci info in basicblock"); |
982 } | |
983 #endif | |
984 } | |
985 #ifdef ASSERT | |
986 { BasicBlock *bb = &_basic_blocks[bbNo-1]; | |
987 address bcp = _method->bcp_from(bb->_end_bci); | |
2142 | 988 int bc_len = Bytecodes::java_length_at(_method(), bcp); |
0 | 989 assert(bb->_end_bci + bc_len == _method->code_size(), "wrong end bci"); |
990 } | |
991 #endif | |
992 | |
993 // Mark all alive blocks | |
994 mark_reachable_code(); | |
995 } | |
996 | |
997 void GenerateOopMap::setup_method_entry_state() { | |
998 | |
999 // Initialize all locals to 'uninit' and set stack-height to 0 | |
1000 make_context_uninitialized(); | |
1001 | |
1002 // Initialize CellState type of arguments | |
1003 methodsig_to_effect(method()->signature(), method()->is_static(), vars()); | |
1004 | |
1005 // If some references must be pre-assigned to null, then set that up | |
1006 initialize_vars(); | |
1007 | |
1008 // This is the start state | |
1009 merge_state_into_bb(&_basic_blocks[0]); | |
1010 | |
1011 assert(_basic_blocks[0].changed(), "we are not getting off the ground"); | |
1012 } | |
1013 | |
1014 // The instruction at bci is changing size by "delta". Update the basic blocks. | |
1015 void GenerateOopMap::update_basic_blocks(int bci, int delta, | |
1016 int new_method_size) { | |
1017 assert(new_method_size >= method()->code_size() + delta, | |
1018 "new method size is too small"); | |
1019 | |
342 | 1020 BitMap::bm_word_t* new_bb_hdr_bits = |
1021 NEW_RESOURCE_ARRAY(BitMap::bm_word_t, | |
1022 BitMap::word_align_up(new_method_size)); | |
1023 _bb_hdr_bits.set_map(new_bb_hdr_bits); | |
1024 _bb_hdr_bits.set_size(new_method_size); | |
1025 _bb_hdr_bits.clear(); | |
0 | 1026 |
1027 | |
1028 for(int k = 0; k < _bb_count; k++) { | |
1029 if (_basic_blocks[k]._bci > bci) { | |
1030 _basic_blocks[k]._bci += delta; | |
1031 _basic_blocks[k]._end_bci += delta; | |
1032 } | |
342 | 1033 _bb_hdr_bits.at_put(_basic_blocks[k]._bci, true); |
0 | 1034 } |
1035 } | |
1036 | |
1037 // | |
1038 // Initvars handling | |
1039 // | |
1040 | |
1041 void GenerateOopMap::initialize_vars() { | |
1042 for (int k = 0; k < _init_vars->length(); k++) | |
1043 _state[_init_vars->at(k)] = CellTypeState::make_slot_ref(k); | |
1044 } | |
1045 | |
1046 void GenerateOopMap::add_to_ref_init_set(int localNo) { | |
1047 | |
1048 if (TraceNewOopMapGeneration) | |
1049 tty->print_cr("Added init vars: %d", localNo); | |
1050 | |
1051 // Is it already in the set? | |
1052 if (_init_vars->contains(localNo) ) | |
1053 return; | |
1054 | |
1055 _init_vars->append(localNo); | |
1056 } | |
1057 | |
1058 // | |
1059 // Interpreration code | |
1060 // | |
1061 | |
1062 void GenerateOopMap::interp_all() { | |
1063 bool change = true; | |
1064 | |
1065 while (change && !_got_error) { | |
1066 change = false; | |
1067 for (int i = 0; i < _bb_count && !_got_error; i++) { | |
1068 BasicBlock *bb = &_basic_blocks[i]; | |
1069 if (bb->changed()) { | |
1070 if (_got_error) return; | |
1071 change = true; | |
1072 bb->set_changed(false); | |
1073 interp_bb(bb); | |
1074 } | |
1075 } | |
1076 } | |
1077 } | |
1078 | |
1079 void GenerateOopMap::interp_bb(BasicBlock *bb) { | |
1080 | |
1081 // We do not want to do anything in case the basic-block has not been initialized. This | |
1082 // will happen in the case where there is dead-code hang around in a method. | |
1083 assert(bb->is_reachable(), "should be reachable or deadcode exist"); | |
1084 restore_state(bb); | |
1085 | |
1086 BytecodeStream itr(_method); | |
1087 | |
1088 // Set iterator interval to be the current basicblock | |
1089 int lim_bci = next_bb_start_pc(bb); | |
1090 itr.set_interval(bb->_bci, lim_bci); | |
1091 assert(lim_bci != bb->_bci, "must be at least one instruction in a basicblock"); | |
1092 itr.next(); // read first instruction | |
1093 | |
1094 // Iterates through all bytecodes except the last in a basic block. | |
1095 // We handle the last one special, since there is controlflow change. | |
1096 while(itr.next_bci() < lim_bci && !_got_error) { | |
1097 if (_has_exceptions || _monitor_top != 0) { | |
1098 // We do not need to interpret the results of exceptional | |
1099 // continuation from this instruction when the method has no | |
1100 // exception handlers and the monitor stack is currently | |
1101 // empty. | |
1102 do_exception_edge(&itr); | |
1103 } | |
1104 interp1(&itr); | |
1105 itr.next(); | |
1106 } | |
1107 | |
1108 // Handle last instruction. | |
1109 if (!_got_error) { | |
1110 assert(itr.next_bci() == lim_bci, "must point to end"); | |
1111 if (_has_exceptions || _monitor_top != 0) { | |
1112 do_exception_edge(&itr); | |
1113 } | |
1114 interp1(&itr); | |
1115 | |
1116 bool fall_through = jump_targets_do(&itr, GenerateOopMap::merge_state, NULL); | |
1117 if (_got_error) return; | |
1118 | |
1119 if (itr.code() == Bytecodes::_ret) { | |
1120 assert(!fall_through, "cannot be set if ret instruction"); | |
1121 // Automatically handles 'wide' ret indicies | |
1122 ret_jump_targets_do(&itr, GenerateOopMap::merge_state, itr.get_index(), NULL); | |
1123 } else if (fall_through) { | |
1124 // Hit end of BB, but the instr. was a fall-through instruction, | |
1125 // so perform transition as if the BB ended in a "jump". | |
1126 if (lim_bci != bb[1]._bci) { | |
1127 verify_error("bytecodes fell through last instruction"); | |
1128 return; | |
1129 } | |
1130 merge_state_into_bb(bb + 1); | |
1131 } | |
1132 } | |
1133 } | |
1134 | |
1135 void GenerateOopMap::do_exception_edge(BytecodeStream* itr) { | |
1136 // Only check exception edge, if bytecode can trap | |
1137 if (!Bytecodes::can_trap(itr->code())) return; | |
1138 switch (itr->code()) { | |
1139 case Bytecodes::_aload_0: | |
1140 // These bytecodes can trap for rewriting. We need to assume that | |
1141 // they do not throw exceptions to make the monitor analysis work. | |
1142 return; | |
1143 | |
1144 case Bytecodes::_ireturn: | |
1145 case Bytecodes::_lreturn: | |
1146 case Bytecodes::_freturn: | |
1147 case Bytecodes::_dreturn: | |
1148 case Bytecodes::_areturn: | |
1149 case Bytecodes::_return: | |
1150 // If the monitor stack height is not zero when we leave the method, | |
1151 // then we are either exiting with a non-empty stack or we have | |
1152 // found monitor trouble earlier in our analysis. In either case, | |
1153 // assume an exception could be taken here. | |
1154 if (_monitor_top == 0) { | |
1155 return; | |
1156 } | |
1157 break; | |
1158 | |
1159 case Bytecodes::_monitorexit: | |
1160 // If the monitor stack height is bad_monitors, then we have detected a | |
1161 // monitor matching problem earlier in the analysis. If the | |
1162 // monitor stack height is 0, we are about to pop a monitor | |
1163 // off of an empty stack. In either case, the bytecode | |
1164 // could throw an exception. | |
1165 if (_monitor_top != bad_monitors && _monitor_top != 0) { | |
1166 return; | |
1167 } | |
1168 break; | |
1169 } | |
1170 | |
1171 if (_has_exceptions) { | |
1172 int bci = itr->bci(); | |
1173 typeArrayOop exct = method()->exception_table(); | |
1174 for(int i = 0; i< exct->length(); i+=4) { | |
1175 int start_pc = exct->int_at(i); | |
1176 int end_pc = exct->int_at(i+1); | |
1177 int handler_pc = exct->int_at(i+2); | |
1178 int catch_type = exct->int_at(i+3); | |
1179 | |
1180 if (start_pc <= bci && bci < end_pc) { | |
1181 BasicBlock *excBB = get_basic_block_at(handler_pc); | |
1182 CellTypeState *excStk = excBB->stack(); | |
1183 CellTypeState *cOpStck = stack(); | |
1184 CellTypeState cOpStck_0 = cOpStck[0]; | |
1185 int cOpStackTop = _stack_top; | |
1186 | |
1187 // Exception stacks are always the same. | |
1188 assert(method()->max_stack() > 0, "sanity check"); | |
1189 | |
1190 // We remembered the size and first element of "cOpStck" | |
1191 // above; now we temporarily set them to the appropriate | |
1192 // values for an exception handler. */ | |
1193 cOpStck[0] = CellTypeState::make_slot_ref(_max_locals); | |
1194 _stack_top = 1; | |
1195 | |
1196 merge_state_into_bb(excBB); | |
1197 | |
1198 // Now undo the temporary change. | |
1199 cOpStck[0] = cOpStck_0; | |
1200 _stack_top = cOpStackTop; | |
1201 | |
1202 // If this is a "catch all" handler, then we do not need to | |
1203 // consider any additional handlers. | |
1204 if (catch_type == 0) { | |
1205 return; | |
1206 } | |
1207 } | |
1208 } | |
1209 } | |
1210 | |
1211 // It is possible that none of the exception handlers would have caught | |
1212 // the exception. In this case, we will exit the method. We must | |
1213 // ensure that the monitor stack is empty in this case. | |
1214 if (_monitor_top == 0) { | |
1215 return; | |
1216 } | |
1217 | |
1218 // We pessimistically assume that this exception can escape the | |
1219 // method. (It is possible that it will always be caught, but | |
1220 // we don't care to analyse the types of the catch clauses.) | |
1221 | |
1222 // We don't set _monitor_top to bad_monitors because there are no successors | |
1223 // to this exceptional exit. | |
1224 | |
1225 if (TraceMonitorMismatch && _monitor_safe) { | |
1226 // We check _monitor_safe so that we only report the first mismatched | |
1227 // exceptional exit. | |
1228 report_monitor_mismatch("non-empty monitor stack at exceptional exit"); | |
1229 } | |
1230 _monitor_safe = false; | |
1231 | |
1232 } | |
1233 | |
1234 void GenerateOopMap::report_monitor_mismatch(const char *msg) { | |
1235 #ifndef PRODUCT | |
1236 tty->print(" Monitor mismatch in method "); | |
1237 method()->print_short_name(tty); | |
1238 tty->print_cr(": %s", msg); | |
1239 #endif | |
1240 } | |
1241 | |
1242 void GenerateOopMap::print_states(outputStream *os, | |
1243 CellTypeState* vec, int num) { | |
1244 for (int i = 0; i < num; i++) { | |
1245 vec[i].print(tty); | |
1246 } | |
1247 } | |
1248 | |
1249 // Print the state values at the current bytecode. | |
1250 void GenerateOopMap::print_current_state(outputStream *os, | |
1251 BytecodeStream *currentBC, | |
1252 bool detailed) { | |
1253 | |
1254 if (detailed) { | |
1255 os->print(" %4d vars = ", currentBC->bci()); | |
1256 print_states(os, vars(), _max_locals); | |
1257 os->print(" %s", Bytecodes::name(currentBC->code())); | |
1258 switch(currentBC->code()) { | |
1259 case Bytecodes::_invokevirtual: | |
1260 case Bytecodes::_invokespecial: | |
1261 case Bytecodes::_invokestatic: | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
1262 case Bytecodes::_invokedynamic: |
0 | 1263 case Bytecodes::_invokeinterface: |
1910
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1264 int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2_cpcache(); |
0 | 1265 constantPoolOop cp = method()->constants(); |
1266 int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); | |
1267 int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
1268 Symbol* signature = cp->symbol_at(signatureIdx); |
0 | 1269 os->print("%s", signature->as_C_string()); |
1270 } | |
1271 os->cr(); | |
1272 os->print(" stack = "); | |
1273 print_states(os, stack(), _stack_top); | |
1274 os->cr(); | |
1275 if (_monitor_top != bad_monitors) { | |
1276 os->print(" monitors = "); | |
1277 print_states(os, monitors(), _monitor_top); | |
1278 } else { | |
1279 os->print(" [bad monitor stack]"); | |
1280 } | |
1281 os->cr(); | |
1282 } else { | |
1283 os->print(" %4d vars = '%s' ", currentBC->bci(), state_vec_to_string(vars(), _max_locals)); | |
1284 os->print(" stack = '%s' ", state_vec_to_string(stack(), _stack_top)); | |
1285 if (_monitor_top != bad_monitors) { | |
1286 os->print(" monitors = '%s' \t%s", state_vec_to_string(monitors(), _monitor_top), Bytecodes::name(currentBC->code())); | |
1287 } else { | |
1288 os->print(" [bad monitor stack]"); | |
1289 } | |
1290 switch(currentBC->code()) { | |
1291 case Bytecodes::_invokevirtual: | |
1292 case Bytecodes::_invokespecial: | |
1293 case Bytecodes::_invokestatic: | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
1294 case Bytecodes::_invokedynamic: |
0 | 1295 case Bytecodes::_invokeinterface: |
1910
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1296 int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2_cpcache(); |
0 | 1297 constantPoolOop cp = method()->constants(); |
1298 int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); | |
1299 int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
1300 Symbol* signature = cp->symbol_at(signatureIdx); |
0 | 1301 os->print("%s", signature->as_C_string()); |
1302 } | |
1303 os->cr(); | |
1304 } | |
1305 } | |
1306 | |
1307 // Sets the current state to be the state after executing the | |
1308 // current instruction, starting in the current state. | |
1309 void GenerateOopMap::interp1(BytecodeStream *itr) { | |
1310 if (TraceNewOopMapGeneration) { | |
1311 print_current_state(tty, itr, TraceNewOopMapGenerationDetailed); | |
1312 } | |
1313 | |
1314 // Should we report the results? Result is reported *before* the instruction at the current bci is executed. | |
1315 // However, not for calls. For calls we do not want to include the arguments, so we postpone the reporting until | |
1316 // they have been popped (in method ppl). | |
1317 if (_report_result == true) { | |
1318 switch(itr->code()) { | |
1319 case Bytecodes::_invokevirtual: | |
1320 case Bytecodes::_invokespecial: | |
1321 case Bytecodes::_invokestatic: | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
1322 case Bytecodes::_invokedynamic: |
0 | 1323 case Bytecodes::_invokeinterface: |
1324 _itr_send = itr; | |
1325 _report_result_for_send = true; | |
1326 break; | |
1327 default: | |
1328 fill_stackmap_for_opcodes(itr, vars(), stack(), _stack_top); | |
1329 break; | |
1330 } | |
1331 } | |
1332 | |
1333 // abstract interpretation of current opcode | |
1334 switch(itr->code()) { | |
1335 case Bytecodes::_nop: break; | |
1336 case Bytecodes::_goto: break; | |
1337 case Bytecodes::_goto_w: break; | |
1338 case Bytecodes::_iinc: break; | |
1339 case Bytecodes::_return: do_return_monitor_check(); | |
1340 break; | |
1341 | |
1342 case Bytecodes::_aconst_null: | |
1343 case Bytecodes::_new: ppush1(CellTypeState::make_line_ref(itr->bci())); | |
1344 break; | |
1345 | |
1346 case Bytecodes::_iconst_m1: | |
1347 case Bytecodes::_iconst_0: | |
1348 case Bytecodes::_iconst_1: | |
1349 case Bytecodes::_iconst_2: | |
1350 case Bytecodes::_iconst_3: | |
1351 case Bytecodes::_iconst_4: | |
1352 case Bytecodes::_iconst_5: | |
1353 case Bytecodes::_fconst_0: | |
1354 case Bytecodes::_fconst_1: | |
1355 case Bytecodes::_fconst_2: | |
1356 case Bytecodes::_bipush: | |
1357 case Bytecodes::_sipush: ppush1(valCTS); break; | |
1358 | |
1359 case Bytecodes::_lconst_0: | |
1360 case Bytecodes::_lconst_1: | |
1361 case Bytecodes::_dconst_0: | |
1362 case Bytecodes::_dconst_1: ppush(vvCTS); break; | |
1363 | |
1364 case Bytecodes::_ldc2_w: ppush(vvCTS); break; | |
1365 | |
1910
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1366 case Bytecodes::_ldc: // fall through: |
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1367 case Bytecodes::_ldc_w: do_ldc(itr->bci()); break; |
0 | 1368 |
1369 case Bytecodes::_iload: | |
1370 case Bytecodes::_fload: ppload(vCTS, itr->get_index()); break; | |
1371 | |
1372 case Bytecodes::_lload: | |
1373 case Bytecodes::_dload: ppload(vvCTS,itr->get_index()); break; | |
1374 | |
1375 case Bytecodes::_aload: ppload(rCTS, itr->get_index()); break; | |
1376 | |
1377 case Bytecodes::_iload_0: | |
1378 case Bytecodes::_fload_0: ppload(vCTS, 0); break; | |
1379 case Bytecodes::_iload_1: | |
1380 case Bytecodes::_fload_1: ppload(vCTS, 1); break; | |
1381 case Bytecodes::_iload_2: | |
1382 case Bytecodes::_fload_2: ppload(vCTS, 2); break; | |
1383 case Bytecodes::_iload_3: | |
1384 case Bytecodes::_fload_3: ppload(vCTS, 3); break; | |
1385 | |
1386 case Bytecodes::_lload_0: | |
1387 case Bytecodes::_dload_0: ppload(vvCTS, 0); break; | |
1388 case Bytecodes::_lload_1: | |
1389 case Bytecodes::_dload_1: ppload(vvCTS, 1); break; | |
1390 case Bytecodes::_lload_2: | |
1391 case Bytecodes::_dload_2: ppload(vvCTS, 2); break; | |
1392 case Bytecodes::_lload_3: | |
1393 case Bytecodes::_dload_3: ppload(vvCTS, 3); break; | |
1394 | |
1395 case Bytecodes::_aload_0: ppload(rCTS, 0); break; | |
1396 case Bytecodes::_aload_1: ppload(rCTS, 1); break; | |
1397 case Bytecodes::_aload_2: ppload(rCTS, 2); break; | |
1398 case Bytecodes::_aload_3: ppload(rCTS, 3); break; | |
1399 | |
1400 case Bytecodes::_iaload: | |
1401 case Bytecodes::_faload: | |
1402 case Bytecodes::_baload: | |
1403 case Bytecodes::_caload: | |
1404 case Bytecodes::_saload: pp(vrCTS, vCTS); break; | |
1405 | |
1406 case Bytecodes::_laload: pp(vrCTS, vvCTS); break; | |
1407 case Bytecodes::_daload: pp(vrCTS, vvCTS); break; | |
1408 | |
1409 case Bytecodes::_aaload: pp_new_ref(vrCTS, itr->bci()); break; | |
1410 | |
1411 case Bytecodes::_istore: | |
1412 case Bytecodes::_fstore: ppstore(vCTS, itr->get_index()); break; | |
1413 | |
1414 case Bytecodes::_lstore: | |
1415 case Bytecodes::_dstore: ppstore(vvCTS, itr->get_index()); break; | |
1416 | |
1417 case Bytecodes::_astore: do_astore(itr->get_index()); break; | |
1418 | |
1419 case Bytecodes::_istore_0: | |
1420 case Bytecodes::_fstore_0: ppstore(vCTS, 0); break; | |
1421 case Bytecodes::_istore_1: | |
1422 case Bytecodes::_fstore_1: ppstore(vCTS, 1); break; | |
1423 case Bytecodes::_istore_2: | |
1424 case Bytecodes::_fstore_2: ppstore(vCTS, 2); break; | |
1425 case Bytecodes::_istore_3: | |
1426 case Bytecodes::_fstore_3: ppstore(vCTS, 3); break; | |
1427 | |
1428 case Bytecodes::_lstore_0: | |
1429 case Bytecodes::_dstore_0: ppstore(vvCTS, 0); break; | |
1430 case Bytecodes::_lstore_1: | |
1431 case Bytecodes::_dstore_1: ppstore(vvCTS, 1); break; | |
1432 case Bytecodes::_lstore_2: | |
1433 case Bytecodes::_dstore_2: ppstore(vvCTS, 2); break; | |
1434 case Bytecodes::_lstore_3: | |
1435 case Bytecodes::_dstore_3: ppstore(vvCTS, 3); break; | |
1436 | |
1437 case Bytecodes::_astore_0: do_astore(0); break; | |
1438 case Bytecodes::_astore_1: do_astore(1); break; | |
1439 case Bytecodes::_astore_2: do_astore(2); break; | |
1440 case Bytecodes::_astore_3: do_astore(3); break; | |
1441 | |
1442 case Bytecodes::_iastore: | |
1443 case Bytecodes::_fastore: | |
1444 case Bytecodes::_bastore: | |
1445 case Bytecodes::_castore: | |
1446 case Bytecodes::_sastore: ppop(vvrCTS); break; | |
1447 case Bytecodes::_lastore: | |
1448 case Bytecodes::_dastore: ppop(vvvrCTS); break; | |
1449 case Bytecodes::_aastore: ppop(rvrCTS); break; | |
1450 | |
1451 case Bytecodes::_pop: ppop_any(1); break; | |
1452 case Bytecodes::_pop2: ppop_any(2); break; | |
1453 | |
1454 case Bytecodes::_dup: ppdupswap(1, "11"); break; | |
1455 case Bytecodes::_dup_x1: ppdupswap(2, "121"); break; | |
1456 case Bytecodes::_dup_x2: ppdupswap(3, "1321"); break; | |
1457 case Bytecodes::_dup2: ppdupswap(2, "2121"); break; | |
1458 case Bytecodes::_dup2_x1: ppdupswap(3, "21321"); break; | |
1459 case Bytecodes::_dup2_x2: ppdupswap(4, "214321"); break; | |
1460 case Bytecodes::_swap: ppdupswap(2, "12"); break; | |
1461 | |
1462 case Bytecodes::_iadd: | |
1463 case Bytecodes::_fadd: | |
1464 case Bytecodes::_isub: | |
1465 case Bytecodes::_fsub: | |
1466 case Bytecodes::_imul: | |
1467 case Bytecodes::_fmul: | |
1468 case Bytecodes::_idiv: | |
1469 case Bytecodes::_fdiv: | |
1470 case Bytecodes::_irem: | |
1471 case Bytecodes::_frem: | |
1472 case Bytecodes::_ishl: | |
1473 case Bytecodes::_ishr: | |
1474 case Bytecodes::_iushr: | |
1475 case Bytecodes::_iand: | |
1476 case Bytecodes::_ior: | |
1477 case Bytecodes::_ixor: | |
1478 case Bytecodes::_l2f: | |
1479 case Bytecodes::_l2i: | |
1480 case Bytecodes::_d2f: | |
1481 case Bytecodes::_d2i: | |
1482 case Bytecodes::_fcmpl: | |
1483 case Bytecodes::_fcmpg: pp(vvCTS, vCTS); break; | |
1484 | |
1485 case Bytecodes::_ladd: | |
1486 case Bytecodes::_dadd: | |
1487 case Bytecodes::_lsub: | |
1488 case Bytecodes::_dsub: | |
1489 case Bytecodes::_lmul: | |
1490 case Bytecodes::_dmul: | |
1491 case Bytecodes::_ldiv: | |
1492 case Bytecodes::_ddiv: | |
1493 case Bytecodes::_lrem: | |
1494 case Bytecodes::_drem: | |
1495 case Bytecodes::_land: | |
1496 case Bytecodes::_lor: | |
1497 case Bytecodes::_lxor: pp(vvvvCTS, vvCTS); break; | |
1498 | |
1499 case Bytecodes::_ineg: | |
1500 case Bytecodes::_fneg: | |
1501 case Bytecodes::_i2f: | |
1502 case Bytecodes::_f2i: | |
1503 case Bytecodes::_i2c: | |
1504 case Bytecodes::_i2s: | |
1505 case Bytecodes::_i2b: pp(vCTS, vCTS); break; | |
1506 | |
1507 case Bytecodes::_lneg: | |
1508 case Bytecodes::_dneg: | |
1509 case Bytecodes::_l2d: | |
1510 case Bytecodes::_d2l: pp(vvCTS, vvCTS); break; | |
1511 | |
1512 case Bytecodes::_lshl: | |
1513 case Bytecodes::_lshr: | |
1514 case Bytecodes::_lushr: pp(vvvCTS, vvCTS); break; | |
1515 | |
1516 case Bytecodes::_i2l: | |
1517 case Bytecodes::_i2d: | |
1518 case Bytecodes::_f2l: | |
1519 case Bytecodes::_f2d: pp(vCTS, vvCTS); break; | |
1520 | |
1521 case Bytecodes::_lcmp: pp(vvvvCTS, vCTS); break; | |
1522 case Bytecodes::_dcmpl: | |
1523 case Bytecodes::_dcmpg: pp(vvvvCTS, vCTS); break; | |
1524 | |
1525 case Bytecodes::_ifeq: | |
1526 case Bytecodes::_ifne: | |
1527 case Bytecodes::_iflt: | |
1528 case Bytecodes::_ifge: | |
1529 case Bytecodes::_ifgt: | |
1530 case Bytecodes::_ifle: | |
1531 case Bytecodes::_tableswitch: ppop1(valCTS); | |
1532 break; | |
1533 case Bytecodes::_ireturn: | |
1534 case Bytecodes::_freturn: do_return_monitor_check(); | |
1535 ppop1(valCTS); | |
1536 break; | |
1537 case Bytecodes::_if_icmpeq: | |
1538 case Bytecodes::_if_icmpne: | |
1539 case Bytecodes::_if_icmplt: | |
1540 case Bytecodes::_if_icmpge: | |
1541 case Bytecodes::_if_icmpgt: | |
1542 case Bytecodes::_if_icmple: ppop(vvCTS); | |
1543 break; | |
1544 | |
1545 case Bytecodes::_lreturn: do_return_monitor_check(); | |
1546 ppop(vvCTS); | |
1547 break; | |
1548 | |
1549 case Bytecodes::_dreturn: do_return_monitor_check(); | |
1550 ppop(vvCTS); | |
1551 break; | |
1552 | |
1553 case Bytecodes::_if_acmpeq: | |
1554 case Bytecodes::_if_acmpne: ppop(rrCTS); break; | |
1555 | |
1556 case Bytecodes::_jsr: do_jsr(itr->dest()); break; | |
1557 case Bytecodes::_jsr_w: do_jsr(itr->dest_w()); break; | |
1558 | |
1559 case Bytecodes::_getstatic: do_field(true, true, | |
1565 | 1560 itr->get_index_u2_cpcache(), |
0 | 1561 itr->bci()); break; |
1565 | 1562 case Bytecodes::_putstatic: do_field(false, true, itr->get_index_u2_cpcache(), itr->bci()); break; |
1563 case Bytecodes::_getfield: do_field(true, false, itr->get_index_u2_cpcache(), itr->bci()); break; | |
1564 case Bytecodes::_putfield: do_field(false, false, itr->get_index_u2_cpcache(), itr->bci()); break; | |
0 | 1565 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1566 case Bytecodes::_invokevirtual: |
1565 | 1567 case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_u2_cpcache(), itr->bci()); break; |
1568 case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_u2_cpcache(), itr->bci()); break; | |
1569 case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_u4(), itr->bci()); break; | |
1570 case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_u2_cpcache(), itr->bci()); break; | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1571 case Bytecodes::_newarray: |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1572 case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; |
0 | 1573 case Bytecodes::_checkcast: do_checkcast(); break; |
1574 case Bytecodes::_arraylength: | |
1575 case Bytecodes::_instanceof: pp(rCTS, vCTS); break; | |
1576 case Bytecodes::_monitorenter: do_monitorenter(itr->bci()); break; | |
1577 case Bytecodes::_monitorexit: do_monitorexit(itr->bci()); break; | |
1578 | |
1579 case Bytecodes::_athrow: // handled by do_exception_edge() BUT ... | |
1580 // vlh(apple): do_exception_edge() does not get | |
1581 // called if method has no exception handlers | |
1582 if ((!_has_exceptions) && (_monitor_top > 0)) { | |
1583 _monitor_safe = false; | |
1584 } | |
1585 break; | |
1586 | |
1587 case Bytecodes::_areturn: do_return_monitor_check(); | |
1588 ppop1(refCTS); | |
1589 break; | |
1590 case Bytecodes::_ifnull: | |
1591 case Bytecodes::_ifnonnull: ppop1(refCTS); break; | |
1592 case Bytecodes::_multianewarray: do_multianewarray(*(itr->bcp()+3), itr->bci()); break; | |
1593 | |
1594 case Bytecodes::_wide: fatal("Iterator should skip this bytecode"); break; | |
1595 case Bytecodes::_ret: break; | |
1596 | |
1597 // Java opcodes | |
1598 case Bytecodes::_lookupswitch: ppop1(valCTS); break; | |
1599 | |
1600 default: | |
1601 tty->print("unexpected opcode: %d\n", itr->code()); | |
1602 ShouldNotReachHere(); | |
1603 break; | |
1604 } | |
1605 } | |
1606 | |
1607 void GenerateOopMap::check_type(CellTypeState expected, CellTypeState actual) { | |
1608 if (!expected.equal_kind(actual)) { | |
1609 verify_error("wrong type on stack (found: %c expected: %c)", actual.to_char(), expected.to_char()); | |
1610 } | |
1611 } | |
1612 | |
1613 void GenerateOopMap::ppstore(CellTypeState *in, int loc_no) { | |
1614 while(!(*in).is_bottom()) { | |
1615 CellTypeState expected =*in++; | |
1616 CellTypeState actual = pop(); | |
1617 check_type(expected, actual); | |
1618 assert(loc_no >= 0, "sanity check"); | |
1619 set_var(loc_no++, actual); | |
1620 } | |
1621 } | |
1622 | |
1623 void GenerateOopMap::ppload(CellTypeState *out, int loc_no) { | |
1624 while(!(*out).is_bottom()) { | |
1625 CellTypeState out1 = *out++; | |
1626 CellTypeState vcts = get_var(loc_no); | |
1627 assert(out1.can_be_reference() || out1.can_be_value(), | |
1628 "can only load refs. and values."); | |
1629 if (out1.is_reference()) { | |
1630 assert(loc_no>=0, "sanity check"); | |
1631 if (!vcts.is_reference()) { | |
1632 // We were asked to push a reference, but the type of the | |
1633 // variable can be something else | |
1634 _conflict = true; | |
1635 if (vcts.can_be_uninit()) { | |
1636 // It is a ref-uninit conflict (at least). If there are other | |
1637 // problems, we'll get them in the next round | |
1638 add_to_ref_init_set(loc_no); | |
1639 vcts = out1; | |
1640 } else { | |
1641 // It wasn't a ref-uninit conflict. So must be a | |
1642 // ref-val or ref-pc conflict. Split the variable. | |
1643 record_refval_conflict(loc_no); | |
1644 vcts = out1; | |
1645 } | |
1646 push(out1); // recover... | |
1647 } else { | |
1648 push(vcts); // preserve reference. | |
1649 } | |
1650 // Otherwise it is a conflict, but one that verification would | |
1651 // have caught if illegal. In particular, it can't be a topCTS | |
1652 // resulting from mergeing two difference pcCTS's since the verifier | |
1653 // would have rejected any use of such a merge. | |
1654 } else { | |
1655 push(out1); // handle val/init conflict | |
1656 } | |
1657 loc_no++; | |
1658 } | |
1659 } | |
1660 | |
1661 void GenerateOopMap::ppdupswap(int poplen, const char *out) { | |
1662 CellTypeState actual[5]; | |
1663 assert(poplen < 5, "this must be less than length of actual vector"); | |
1664 | |
1665 // pop all arguments | |
1666 for(int i = 0; i < poplen; i++) actual[i] = pop(); | |
1667 | |
1668 // put them back | |
1669 char push_ch = *out++; | |
1670 while (push_ch != '\0') { | |
1671 int idx = push_ch - '1'; | |
1672 assert(idx >= 0 && idx < poplen, "wrong arguments"); | |
1673 push(actual[idx]); | |
1674 push_ch = *out++; | |
1675 } | |
1676 } | |
1677 | |
1678 void GenerateOopMap::ppop1(CellTypeState out) { | |
1679 CellTypeState actual = pop(); | |
1680 check_type(out, actual); | |
1681 } | |
1682 | |
1683 void GenerateOopMap::ppop(CellTypeState *out) { | |
1684 while (!(*out).is_bottom()) { | |
1685 ppop1(*out++); | |
1686 } | |
1687 } | |
1688 | |
1689 void GenerateOopMap::ppush1(CellTypeState in) { | |
1690 assert(in.is_reference() | in.is_value(), "sanity check"); | |
1691 push(in); | |
1692 } | |
1693 | |
1694 void GenerateOopMap::ppush(CellTypeState *in) { | |
1695 while (!(*in).is_bottom()) { | |
1696 ppush1(*in++); | |
1697 } | |
1698 } | |
1699 | |
1700 void GenerateOopMap::pp(CellTypeState *in, CellTypeState *out) { | |
1701 ppop(in); | |
1702 ppush(out); | |
1703 } | |
1704 | |
1705 void GenerateOopMap::pp_new_ref(CellTypeState *in, int bci) { | |
1706 ppop(in); | |
1707 ppush1(CellTypeState::make_line_ref(bci)); | |
1708 } | |
1709 | |
1710 void GenerateOopMap::ppop_any(int poplen) { | |
1711 if (_stack_top >= poplen) { | |
1712 _stack_top -= poplen; | |
1713 } else { | |
1714 verify_error("stack underflow"); | |
1715 } | |
1716 } | |
1717 | |
1718 // Replace all occurences of the state 'match' with the state 'replace' | |
1719 // in our current state vector. | |
1720 void GenerateOopMap::replace_all_CTS_matches(CellTypeState match, | |
1721 CellTypeState replace) { | |
1722 int i; | |
1723 int len = _max_locals + _stack_top; | |
1724 bool change = false; | |
1725 | |
1726 for (i = len - 1; i >= 0; i--) { | |
1727 if (match.equal(_state[i])) { | |
1728 _state[i] = replace; | |
1729 } | |
1730 } | |
1731 | |
1732 if (_monitor_top > 0) { | |
1733 int base = _max_locals + _max_stack; | |
1734 len = base + _monitor_top; | |
1735 for (i = len - 1; i >= base; i--) { | |
1736 if (match.equal(_state[i])) { | |
1737 _state[i] = replace; | |
1738 } | |
1739 } | |
1740 } | |
1741 } | |
1742 | |
1743 void GenerateOopMap::do_checkcast() { | |
1744 CellTypeState actual = pop(); | |
1745 check_type(refCTS, actual); | |
1746 push(actual); | |
1747 } | |
1748 | |
1749 void GenerateOopMap::do_monitorenter(int bci) { | |
1750 CellTypeState actual = pop(); | |
1751 if (_monitor_top == bad_monitors) { | |
1752 return; | |
1753 } | |
1754 | |
1755 // Bail out when we get repeated locks on an identical monitor. This case | |
1756 // isn't too hard to handle and can be made to work if supporting nested | |
1757 // redundant synchronized statements becomes a priority. | |
1758 // | |
1759 // See also "Note" in do_monitorexit(), below. | |
1760 if (actual.is_lock_reference()) { | |
1761 _monitor_top = bad_monitors; | |
1762 _monitor_safe = false; | |
1763 | |
1764 if (TraceMonitorMismatch) { | |
1765 report_monitor_mismatch("nested redundant lock -- bailout..."); | |
1766 } | |
1767 return; | |
1768 } | |
1769 | |
1770 CellTypeState lock = CellTypeState::make_lock_ref(bci); | |
1771 check_type(refCTS, actual); | |
1772 if (!actual.is_info_top()) { | |
1773 replace_all_CTS_matches(actual, lock); | |
1774 monitor_push(lock); | |
1775 } | |
1776 } | |
1777 | |
1778 void GenerateOopMap::do_monitorexit(int bci) { | |
1779 CellTypeState actual = pop(); | |
1780 if (_monitor_top == bad_monitors) { | |
1781 return; | |
1782 } | |
1783 check_type(refCTS, actual); | |
1784 CellTypeState expected = monitor_pop(); | |
1785 if (!actual.is_lock_reference() || !expected.equal(actual)) { | |
1786 // The monitor we are exiting is not verifiably the one | |
1787 // on the top of our monitor stack. This causes a monitor | |
1788 // mismatch. | |
1789 _monitor_top = bad_monitors; | |
1790 _monitor_safe = false; | |
1791 | |
1792 // We need to mark this basic block as changed so that | |
1793 // this monitorexit will be visited again. We need to | |
1794 // do this to ensure that we have accounted for the | |
1795 // possibility that this bytecode will throw an | |
1796 // exception. | |
1797 BasicBlock* bb = get_basic_block_containing(bci); | |
1798 bb->set_changed(true); | |
1799 bb->_monitor_top = bad_monitors; | |
1800 | |
1801 if (TraceMonitorMismatch) { | |
1802 report_monitor_mismatch("improper monitor pair"); | |
1803 } | |
1804 } else { | |
1805 // This code is a fix for the case where we have repeated | |
1806 // locking of the same object in straightline code. We clear | |
1807 // out the lock when it is popped from the monitor stack | |
1808 // and replace it with an unobtrusive reference value that can | |
1809 // be locked again. | |
1810 // | |
1811 // Note: when generateOopMap is fixed to properly handle repeated, | |
1812 // nested, redundant locks on the same object, then this | |
1813 // fix will need to be removed at that time. | |
1814 replace_all_CTS_matches(actual, CellTypeState::make_line_ref(bci)); | |
1815 } | |
1816 } | |
1817 | |
1818 void GenerateOopMap::do_return_monitor_check() { | |
1819 if (_monitor_top > 0) { | |
1820 // The monitor stack must be empty when we leave the method | |
1821 // for the monitors to be properly matched. | |
1822 _monitor_safe = false; | |
1823 | |
1824 // Since there are no successors to the *return bytecode, it | |
1825 // isn't necessary to set _monitor_top to bad_monitors. | |
1826 | |
1827 if (TraceMonitorMismatch) { | |
1828 report_monitor_mismatch("non-empty monitor stack at return"); | |
1829 } | |
1830 } | |
1831 } | |
1832 | |
1833 void GenerateOopMap::do_jsr(int targ_bci) { | |
1834 push(CellTypeState::make_addr(targ_bci)); | |
1835 } | |
1836 | |
1837 | |
1838 | |
1910
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1839 void GenerateOopMap::do_ldc(int bci) { |
2142 | 1840 Bytecode_loadconstant ldc(method(), bci); |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1059
diff
changeset
|
1841 constantPoolOop cp = method()->constants(); |
2142 | 1842 BasicType bt = ldc.result_type(); |
1910
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1843 CellTypeState cts = (bt == T_OBJECT) ? CellTypeState::make_line_ref(bci) : valCTS; |
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1844 // Make sure bt==T_OBJECT is the same as old code (is_pointer_entry). |
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1845 // Note that CONSTANT_MethodHandle entries are u2 index pairs, not pointer-entries, |
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1846 // and they are processed by _fast_aldc and the CP cache. |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
1847 assert((ldc.has_cache_index() || cp->is_object_entry(ldc.pool_index())) |
1910
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1681
diff
changeset
|
1848 ? (bt == T_OBJECT) : true, "expected object type"); |
0 | 1849 ppush1(cts); |
1850 } | |
1851 | |
1852 void GenerateOopMap::do_multianewarray(int dims, int bci) { | |
1853 assert(dims >= 1, "sanity check"); | |
1854 for(int i = dims -1; i >=0; i--) { | |
1855 ppop1(valCTS); | |
1856 } | |
1857 ppush1(CellTypeState::make_line_ref(bci)); | |
1858 } | |
1859 | |
1860 void GenerateOopMap::do_astore(int idx) { | |
1861 CellTypeState r_or_p = pop(); | |
1862 if (!r_or_p.is_address() && !r_or_p.is_reference()) { | |
1863 // We actually expected ref or pc, but we only report that we expected a ref. It does not | |
1864 // really matter (at least for now) | |
1865 verify_error("wrong type on stack (found: %c, expected: {pr})", r_or_p.to_char()); | |
1866 return; | |
1867 } | |
1868 set_var(idx, r_or_p); | |
1869 } | |
1870 | |
1871 // Copies bottom/zero terminated CTS string from "src" into "dst". | |
1872 // Does NOT terminate with a bottom. Returns the number of cells copied. | |
1873 int GenerateOopMap::copy_cts(CellTypeState *dst, CellTypeState *src) { | |
1874 int idx = 0; | |
1875 while (!src[idx].is_bottom()) { | |
1876 dst[idx] = src[idx]; | |
1877 idx++; | |
1878 } | |
1879 return idx; | |
1880 } | |
1881 | |
1882 void GenerateOopMap::do_field(int is_get, int is_static, int idx, int bci) { | |
1883 // Dig up signature for field in constant pool | |
1884 constantPoolOop cp = method()->constants(); | |
1885 int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); | |
1886 int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
1887 Symbol* signature = cp->symbol_at(signatureIdx); |
0 | 1888 |
1889 // Parse signature (espcially simple for fields) | |
1890 assert(signature->utf8_length() > 0, "field signatures cannot have zero length"); | |
1891 // The signature is UFT8 encoded, but the first char is always ASCII for signatures. | |
1892 char sigch = (char)*(signature->base()); | |
1893 CellTypeState temp[4]; | |
1894 CellTypeState *eff = sigchar_to_effect(sigch, bci, temp); | |
1895 | |
1896 CellTypeState in[4]; | |
1897 CellTypeState *out; | |
1898 int i = 0; | |
1899 | |
1900 if (is_get) { | |
1901 out = eff; | |
1902 } else { | |
1903 out = epsilonCTS; | |
1904 i = copy_cts(in, eff); | |
1905 } | |
1906 if (!is_static) in[i++] = CellTypeState::ref; | |
1907 in[i] = CellTypeState::bottom; | |
1908 assert(i<=3, "sanity check"); | |
1909 pp(in, out); | |
1910 } | |
1911 | |
1912 void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) { | |
1059
389049f3f393
6858164: invokedynamic code needs some cleanup (post-6655638)
jrose
parents:
844
diff
changeset
|
1913 // Dig up signature for field in constant pool |
389049f3f393
6858164: invokedynamic code needs some cleanup (post-6655638)
jrose
parents:
844
diff
changeset
|
1914 constantPoolOop cp = _method->constants(); |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
1915 Symbol* signature = cp->signature_ref_at(idx); |
0 | 1916 |
1917 // Parse method signature | |
1918 CellTypeState out[4]; | |
1919 CellTypeState in[MAXARGSIZE+1]; // Includes result | |
1920 ComputeCallStack cse(signature); | |
1921 | |
1922 // Compute return type | |
1923 int res_length= cse.compute_for_returntype(out); | |
1924 | |
1925 // Temporary hack. | |
1926 if (out[0].equal(CellTypeState::ref) && out[1].equal(CellTypeState::bottom)) { | |
1927 out[0] = CellTypeState::make_line_ref(bci); | |
1928 } | |
1929 | |
1930 assert(res_length<=4, "max value should be vv"); | |
1931 | |
1932 // Compute arguments | |
1933 int arg_length = cse.compute_for_parameters(is_static != 0, in); | |
1934 assert(arg_length<=MAXARGSIZE, "too many locals"); | |
1935 | |
1936 // Pop arguments | |
1937 for (int i = arg_length - 1; i >= 0; i--) ppop1(in[i]);// Do args in reverse order. | |
1938 | |
1939 // Report results | |
1940 if (_report_result_for_send == true) { | |
1941 fill_stackmap_for_opcodes(_itr_send, vars(), stack(), _stack_top); | |
1942 _report_result_for_send = false; | |
1943 } | |
1944 | |
1945 // Push return address | |
1946 ppush(out); | |
1947 } | |
1948 | |
1949 // This is used to parse the signature for fields, since they are very simple... | |
1950 CellTypeState *GenerateOopMap::sigchar_to_effect(char sigch, int bci, CellTypeState *out) { | |
1951 // Object and array | |
1952 if (sigch=='L' || sigch=='[') { | |
1953 out[0] = CellTypeState::make_line_ref(bci); | |
1954 out[1] = CellTypeState::bottom; | |
1955 return out; | |
1956 } | |
1957 if (sigch == 'J' || sigch == 'D' ) return vvCTS; // Long and Double | |
1958 if (sigch == 'V' ) return epsilonCTS; // Void | |
1959 return vCTS; // Otherwise | |
1960 } | |
1961 | |
1962 long GenerateOopMap::_total_byte_count = 0; | |
1963 elapsedTimer GenerateOopMap::_total_oopmap_time; | |
1964 | |
1965 // This function assumes "bcs" is at a "ret" instruction and that the vars | |
1966 // state is valid for that instruction. Furthermore, the ret instruction | |
1967 // must be the last instruction in "bb" (we store information about the | |
1968 // "ret" in "bb"). | |
1969 void GenerateOopMap::ret_jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int varNo, int *data) { | |
1970 CellTypeState ra = vars()[varNo]; | |
1971 if (!ra.is_good_address()) { | |
1972 verify_error("ret returns from two jsr subroutines?"); | |
1973 return; | |
1974 } | |
1975 int target = ra.get_info(); | |
1976 | |
1977 RetTableEntry* rtEnt = _rt.find_jsrs_for_target(target); | |
1978 int bci = bcs->bci(); | |
1979 for (int i = 0; i < rtEnt->nof_jsrs(); i++) { | |
1980 int target_bci = rtEnt->jsrs(i); | |
1981 // Make sure a jrtRet does not set the changed bit for dead basicblock. | |
1982 BasicBlock* jsr_bb = get_basic_block_containing(target_bci - 1); | |
1983 debug_only(BasicBlock* target_bb = &jsr_bb[1];) | |
1984 assert(target_bb == get_basic_block_at(target_bci), "wrong calc. of successor basicblock"); | |
1985 bool alive = jsr_bb->is_alive(); | |
1986 if (TraceNewOopMapGeneration) { | |
1987 tty->print("pc = %d, ret -> %d alive: %s\n", bci, target_bci, alive ? "true" : "false"); | |
1988 } | |
1989 if (alive) jmpFct(this, target_bci, data); | |
1990 } | |
1991 } | |
1992 | |
1993 // | |
1994 // Debug method | |
1995 // | |
1996 char* GenerateOopMap::state_vec_to_string(CellTypeState* vec, int len) { | |
1997 #ifdef ASSERT | |
1998 int checklen = MAX3(_max_locals, _max_stack, _max_monitors) + 1; | |
1999 assert(len < checklen, "state_vec_buf overflow"); | |
2000 #endif | |
2001 for (int i = 0; i < len; i++) _state_vec_buf[i] = vec[i].to_char(); | |
2002 _state_vec_buf[len] = 0; | |
2003 return _state_vec_buf; | |
2004 } | |
2005 | |
2006 void GenerateOopMap::print_time() { | |
2007 tty->print_cr ("Accumulated oopmap times:"); | |
2008 tty->print_cr ("---------------------------"); | |
2009 tty->print_cr (" Total : %3.3f sec.", GenerateOopMap::_total_oopmap_time.seconds()); | |
2010 tty->print_cr (" (%3.0f bytecodes per sec) ", | |
2011 GenerateOopMap::_total_byte_count / GenerateOopMap::_total_oopmap_time.seconds()); | |
2012 } | |
2013 | |
2014 // | |
2015 // ============ Main Entry Point =========== | |
2016 // | |
2017 GenerateOopMap::GenerateOopMap(methodHandle method) { | |
605 | 2018 // We have to initialize all variables here, that can be queried directly |
0 | 2019 _method = method; |
2020 _max_locals=0; | |
2021 _init_vars = NULL; | |
2022 | |
2023 #ifndef PRODUCT | |
2024 // If we are doing a detailed trace, include the regular trace information. | |
2025 if (TraceNewOopMapGenerationDetailed) { | |
2026 TraceNewOopMapGeneration = true; | |
2027 } | |
2028 #endif | |
2029 } | |
2030 | |
2031 void GenerateOopMap::compute_map(TRAPS) { | |
2032 #ifndef PRODUCT | |
2033 if (TimeOopMap2) { | |
2034 method()->print_short_name(tty); | |
2035 tty->print(" "); | |
2036 } | |
2037 if (TimeOopMap) { | |
2038 _total_byte_count += method()->code_size(); | |
2039 } | |
2040 #endif | |
2041 TraceTime t_single("oopmap time", TimeOopMap2); | |
2042 TraceTime t_all(NULL, &_total_oopmap_time, TimeOopMap); | |
2043 | |
2044 // Initialize values | |
2045 _got_error = false; | |
2046 _conflict = false; | |
2047 _max_locals = method()->max_locals(); | |
2048 _max_stack = method()->max_stack(); | |
2049 _has_exceptions = (method()->exception_table()->length() > 0); | |
2050 _nof_refval_conflicts = 0; | |
2051 _init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars | |
2052 _report_result = false; | |
2053 _report_result_for_send = false; | |
2054 _new_var_map = NULL; | |
2055 _ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number; | |
2056 _did_rewriting = false; | |
2057 _did_relocation = false; | |
2058 | |
2059 if (TraceNewOopMapGeneration) { | |
2060 tty->print("Method name: %s\n", method()->name()->as_C_string()); | |
2061 if (Verbose) { | |
2062 _method->print_codes(); | |
2063 tty->print_cr("Exception table:"); | |
2064 typeArrayOop excps = method()->exception_table(); | |
2065 for(int i = 0; i < excps->length(); i += 4) { | |
2066 tty->print_cr("[%d - %d] -> %d", excps->int_at(i + 0), excps->int_at(i + 1), excps->int_at(i + 2)); | |
2067 } | |
2068 } | |
2069 } | |
2070 | |
2071 // if no code - do nothing | |
2072 // compiler needs info | |
2073 if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) { | |
2074 fill_stackmap_prolog(0); | |
2075 fill_stackmap_epilog(); | |
2076 return; | |
2077 } | |
2078 // Step 1: Compute all jump targets and their return value | |
2079 if (!_got_error) | |
2080 _rt.compute_ret_table(_method); | |
2081 | |
2082 // Step 2: Find all basic blocks and count GC points | |
2083 if (!_got_error) | |
2084 mark_bbheaders_and_count_gc_points(); | |
2085 | |
2086 // Step 3: Calculate stack maps | |
2087 if (!_got_error) | |
2088 do_interpretation(); | |
2089 | |
2090 // Step 4:Return results | |
2091 if (!_got_error && report_results()) | |
2092 report_result(); | |
2093 | |
2094 if (_got_error) { | |
2095 THROW_HANDLE(_exception); | |
2096 } | |
2097 } | |
2098 | |
2099 // Error handling methods | |
2100 // These methods create an exception for the current thread which is thrown | |
2101 // at the bottom of the call stack, when it returns to compute_map(). The | |
2102 // _got_error flag controls execution. NOT TODO: The VM exception propagation | |
2103 // mechanism using TRAPS/CHECKs could be used here instead but it would need | |
2104 // to be added as a parameter to every function and checked for every call. | |
2105 // The tons of extra code it would generate didn't seem worth the change. | |
2106 // | |
2107 void GenerateOopMap::error_work(const char *format, va_list ap) { | |
2108 _got_error = true; | |
2109 char msg_buffer[512]; | |
2110 vsnprintf(msg_buffer, sizeof(msg_buffer), format, ap); | |
2111 // Append method name | |
2112 char msg_buffer2[512]; | |
2113 jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string()); | |
2114 _exception = Exceptions::new_exception(Thread::current(), | |
2115 vmSymbols::java_lang_LinkageError(), msg_buffer2); | |
2116 } | |
2117 | |
2118 void GenerateOopMap::report_error(const char *format, ...) { | |
2119 va_list ap; | |
2120 va_start(ap, format); | |
2121 error_work(format, ap); | |
2122 } | |
2123 | |
2124 void GenerateOopMap::verify_error(const char *format, ...) { | |
2125 // We do not distinguish between different types of errors for verification | |
2126 // errors. Let the verifier give a better message. | |
2127 const char *msg = "Illegal class file encountered. Try running with -Xverify:all"; | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
2128 _got_error = true; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
2129 // Append method name |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
2130 char msg_buffer2[512]; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
2131 jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg, |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
2132 method()->name()->as_C_string()); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
2133 _exception = Exceptions::new_exception(Thread::current(), |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
2134 vmSymbols::java_lang_LinkageError(), msg_buffer2); |
0 | 2135 } |
2136 | |
2137 // | |
2138 // Report result opcodes | |
2139 // | |
2140 void GenerateOopMap::report_result() { | |
2141 | |
2142 if (TraceNewOopMapGeneration) tty->print_cr("Report result pass"); | |
2143 | |
2144 // We now want to report the result of the parse | |
2145 _report_result = true; | |
2146 | |
2147 // Prolog code | |
2148 fill_stackmap_prolog(_gc_points); | |
2149 | |
2150 // Mark everything changed, then do one interpretation pass. | |
2151 for (int i = 0; i<_bb_count; i++) { | |
2152 if (_basic_blocks[i].is_reachable()) { | |
2153 _basic_blocks[i].set_changed(true); | |
2154 interp_bb(&_basic_blocks[i]); | |
2155 } | |
2156 } | |
2157 | |
2158 // Note: Since we are skipping dead-code when we are reporting results, then | |
2159 // the no. of encountered gc-points might be fewer than the previously number | |
2160 // we have counted. (dead-code is a pain - it should be removed before we get here) | |
2161 fill_stackmap_epilog(); | |
2162 | |
2163 // Report initvars | |
2164 fill_init_vars(_init_vars); | |
2165 | |
2166 _report_result = false; | |
2167 } | |
2168 | |
2169 void GenerateOopMap::result_for_basicblock(int bci) { | |
2170 if (TraceNewOopMapGeneration) tty->print_cr("Report result pass for basicblock"); | |
2171 | |
2172 // We now want to report the result of the parse | |
2173 _report_result = true; | |
2174 | |
2175 // Find basicblock and report results | |
2176 BasicBlock* bb = get_basic_block_containing(bci); | |
2177 assert(bb->is_reachable(), "getting result from unreachable basicblock"); | |
2178 bb->set_changed(true); | |
2179 interp_bb(bb); | |
2180 } | |
2181 | |
2182 // | |
2183 // Conflict handling code | |
2184 // | |
2185 | |
2186 void GenerateOopMap::record_refval_conflict(int varNo) { | |
2187 assert(varNo>=0 && varNo< _max_locals, "index out of range"); | |
2188 | |
2189 if (TraceOopMapRewrites) { | |
2190 tty->print("### Conflict detected (local no: %d)\n", varNo); | |
2191 } | |
2192 | |
2193 if (!_new_var_map) { | |
2194 _new_var_map = NEW_RESOURCE_ARRAY(int, _max_locals); | |
2195 for (int k = 0; k < _max_locals; k++) _new_var_map[k] = k; | |
2196 } | |
2197 | |
2198 if ( _new_var_map[varNo] == varNo) { | |
2199 // Check if max. number of locals has been reached | |
2200 if (_max_locals + _nof_refval_conflicts >= MAX_LOCAL_VARS) { | |
2201 report_error("Rewriting exceeded local variable limit"); | |
2202 return; | |
2203 } | |
2204 _new_var_map[varNo] = _max_locals + _nof_refval_conflicts; | |
2205 _nof_refval_conflicts++; | |
2206 } | |
2207 } | |
2208 | |
2209 void GenerateOopMap::rewrite_refval_conflicts() | |
2210 { | |
2211 // We can get here two ways: Either a rewrite conflict was detected, or | |
2212 // an uninitialize reference was detected. In the second case, we do not | |
2213 // do any rewriting, we just want to recompute the reference set with the | |
2214 // new information | |
2215 | |
2216 int nof_conflicts = 0; // Used for debugging only | |
2217 | |
2218 if ( _nof_refval_conflicts == 0 ) | |
2219 return; | |
2220 | |
2221 // Check if rewrites are allowed in this parse. | |
2222 if (!allow_rewrites() && !IgnoreRewrites) { | |
2223 fatal("Rewriting method not allowed at this stage"); | |
2224 } | |
2225 | |
2226 | |
2227 // This following flag is to tempoary supress rewrites. The locals that might conflict will | |
2228 // all be set to contain values. This is UNSAFE - however, until the rewriting has been completely | |
2229 // tested it is nice to have. | |
2230 if (IgnoreRewrites) { | |
2231 if (Verbose) { | |
2232 tty->print("rewrites suppressed for local no. "); | |
2233 for (int l = 0; l < _max_locals; l++) { | |
2234 if (_new_var_map[l] != l) { | |
2235 tty->print("%d ", l); | |
2236 vars()[l] = CellTypeState::value; | |
2237 } | |
2238 } | |
2239 tty->cr(); | |
2240 } | |
2241 | |
2242 // That was that... | |
2243 _new_var_map = NULL; | |
2244 _nof_refval_conflicts = 0; | |
2245 _conflict = false; | |
2246 | |
2247 return; | |
2248 } | |
2249 | |
2250 // Tracing flag | |
2251 _did_rewriting = true; | |
2252 | |
2253 if (TraceOopMapRewrites) { | |
2254 tty->print_cr("ref/value conflict for method %s - bytecodes are getting rewritten", method()->name()->as_C_string()); | |
2255 method()->print(); | |
2256 method()->print_codes(); | |
2257 } | |
2258 | |
2259 assert(_new_var_map!=NULL, "nothing to rewrite"); | |
2260 assert(_conflict==true, "We should not be here"); | |
2261 | |
2262 compute_ret_adr_at_TOS(); | |
2263 if (!_got_error) { | |
2264 for (int k = 0; k < _max_locals && !_got_error; k++) { | |
2265 if (_new_var_map[k] != k) { | |
2266 if (TraceOopMapRewrites) { | |
2267 tty->print_cr("Rewriting: %d -> %d", k, _new_var_map[k]); | |
2268 } | |
2269 rewrite_refval_conflict(k, _new_var_map[k]); | |
2270 if (_got_error) return; | |
2271 nof_conflicts++; | |
2272 } | |
2273 } | |
2274 } | |
2275 | |
2276 assert(nof_conflicts == _nof_refval_conflicts, "sanity check"); | |
2277 | |
2278 // Adjust the number of locals | |
2279 method()->set_max_locals(_max_locals+_nof_refval_conflicts); | |
2280 _max_locals += _nof_refval_conflicts; | |
2281 | |
2282 // That was that... | |
2283 _new_var_map = NULL; | |
2284 _nof_refval_conflicts = 0; | |
2285 } | |
2286 | |
2287 void GenerateOopMap::rewrite_refval_conflict(int from, int to) { | |
2288 bool startOver; | |
2289 do { | |
2290 // Make sure that the BytecodeStream is constructed in the loop, since | |
2291 // during rewriting a new method oop is going to be used, and the next time | |
2292 // around we want to use that. | |
2293 BytecodeStream bcs(_method); | |
2294 startOver = false; | |
2295 | |
2296 while( bcs.next() >=0 && !startOver && !_got_error) { | |
2297 startOver = rewrite_refval_conflict_inst(&bcs, from, to); | |
2298 } | |
2299 } while (startOver && !_got_error); | |
2300 } | |
2301 | |
2302 /* If the current instruction is one that uses local variable "from" | |
2303 in a ref way, change it to use "to". There's a subtle reason why we | |
2304 renumber the ref uses and not the non-ref uses: non-ref uses may be | |
2305 2 slots wide (double, long) which would necessitate keeping track of | |
2306 whether we should add one or two variables to the method. If the change | |
2307 affected the width of some instruction, returns "TRUE"; otherwise, returns "FALSE". | |
2308 Another reason for moving ref's value is for solving (addr, ref) conflicts, which | |
2309 both uses aload/astore methods. | |
2310 */ | |
2311 bool GenerateOopMap::rewrite_refval_conflict_inst(BytecodeStream *itr, int from, int to) { | |
2312 Bytecodes::Code bc = itr->code(); | |
2313 int index; | |
2314 int bci = itr->bci(); | |
2315 | |
2316 if (is_aload(itr, &index) && index == from) { | |
2317 if (TraceOopMapRewrites) { | |
2318 tty->print_cr("Rewriting aload at bci: %d", bci); | |
2319 } | |
2320 return rewrite_load_or_store(itr, Bytecodes::_aload, Bytecodes::_aload_0, to); | |
2321 } | |
2322 | |
2323 if (is_astore(itr, &index) && index == from) { | |
2324 if (!stack_top_holds_ret_addr(bci)) { | |
2325 if (TraceOopMapRewrites) { | |
2326 tty->print_cr("Rewriting astore at bci: %d", bci); | |
2327 } | |
2328 return rewrite_load_or_store(itr, Bytecodes::_astore, Bytecodes::_astore_0, to); | |
2329 } else { | |
2330 if (TraceOopMapRewrites) { | |
2331 tty->print_cr("Supress rewriting of astore at bci: %d", bci); | |
2332 } | |
2333 } | |
2334 } | |
2335 | |
2336 return false; | |
2337 } | |
2338 | |
2339 // The argument to this method is: | |
2340 // bc : Current bytecode | |
2341 // bcN : either _aload or _astore | |
2342 // bc0 : either _aload_0 or _astore_0 | |
2343 bool GenerateOopMap::rewrite_load_or_store(BytecodeStream *bcs, Bytecodes::Code bcN, Bytecodes::Code bc0, unsigned int varNo) { | |
2344 assert(bcN == Bytecodes::_astore || bcN == Bytecodes::_aload, "wrong argument (bcN)"); | |
2345 assert(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0, "wrong argument (bc0)"); | |
2142 | 2346 int ilen = Bytecodes::length_at(_method(), bcs->bcp()); |
0 | 2347 int newIlen; |
2348 | |
2349 if (ilen == 4) { | |
2350 // Original instruction was wide; keep it wide for simplicity | |
2351 newIlen = 4; | |
2352 } else if (varNo < 4) | |
2353 newIlen = 1; | |
2354 else if (varNo >= 256) | |
2355 newIlen = 4; | |
2356 else | |
2357 newIlen = 2; | |
2358 | |
2359 // If we need to relocate in order to patch the byte, we | |
2360 // do the patching in a temp. buffer, that is passed to the reloc. | |
2361 // The patching of the bytecode stream is then done by the Relocator. | |
2362 // This is neccesary, since relocating the instruction at a certain bci, might | |
2363 // also relocate that instruction, e.g., if a _goto before it gets widen to a _goto_w. | |
2364 // Hence, we do not know which bci to patch after relocation. | |
2365 | |
2366 assert(newIlen <= 4, "sanity check"); | |
2367 u_char inst_buffer[4]; // Max. instruction size is 4. | |
2368 address bcp; | |
2369 | |
2370 if (newIlen != ilen) { | |
2371 // Relocation needed do patching in temp. buffer | |
2372 bcp = (address)inst_buffer; | |
2373 } else { | |
2374 bcp = _method->bcp_from(bcs->bci()); | |
2375 } | |
2376 | |
2377 // Patch either directly in methodOop or in temp. buffer | |
2378 if (newIlen == 1) { | |
2379 assert(varNo < 4, "varNo too large"); | |
2380 *bcp = bc0 + varNo; | |
2381 } else if (newIlen == 2) { | |
2382 assert(varNo < 256, "2-byte index needed!"); | |
2383 *(bcp + 0) = bcN; | |
2384 *(bcp + 1) = varNo; | |
2385 } else { | |
2386 assert(newIlen == 4, "Wrong instruction length"); | |
2387 *(bcp + 0) = Bytecodes::_wide; | |
2388 *(bcp + 1) = bcN; | |
2389 Bytes::put_Java_u2(bcp+2, varNo); | |
2390 } | |
2391 | |
2392 if (newIlen != ilen) { | |
2393 expand_current_instr(bcs->bci(), ilen, newIlen, inst_buffer); | |
2394 } | |
2395 | |
2396 | |
2397 return (newIlen != ilen); | |
2398 } | |
2399 | |
2400 class RelocCallback : public RelocatorListener { | |
2401 private: | |
2402 GenerateOopMap* _gom; | |
2403 public: | |
2404 RelocCallback(GenerateOopMap* gom) { _gom = gom; }; | |
2405 | |
2406 // Callback method | |
2407 virtual void relocated(int bci, int delta, int new_code_length) { | |
2408 _gom->update_basic_blocks (bci, delta, new_code_length); | |
2409 _gom->update_ret_adr_at_TOS(bci, delta); | |
2410 _gom->_rt.update_ret_table (bci, delta); | |
2411 } | |
2412 }; | |
2413 | |
2414 // Returns true if expanding was succesful. Otherwise, reports an error and | |
2415 // returns false. | |
2416 void GenerateOopMap::expand_current_instr(int bci, int ilen, int newIlen, u_char inst_buffer[]) { | |
2417 Thread *THREAD = Thread::current(); // Could really have TRAPS argument. | |
2418 RelocCallback rcb(this); | |
2419 Relocator rc(_method, &rcb); | |
2420 methodHandle m= rc.insert_space_at(bci, newIlen, inst_buffer, THREAD); | |
2421 if (m.is_null() || HAS_PENDING_EXCEPTION) { | |
2422 report_error("could not rewrite method - exception occurred or bytecode buffer overflow"); | |
2423 return; | |
2424 } | |
2425 | |
2426 // Relocator returns a new method oop. | |
2427 _did_relocation = true; | |
2428 _method = m; | |
2429 } | |
2430 | |
2431 | |
2432 bool GenerateOopMap::is_astore(BytecodeStream *itr, int *index) { | |
2433 Bytecodes::Code bc = itr->code(); | |
2434 switch(bc) { | |
2435 case Bytecodes::_astore_0: | |
2436 case Bytecodes::_astore_1: | |
2437 case Bytecodes::_astore_2: | |
2438 case Bytecodes::_astore_3: | |
2439 *index = bc - Bytecodes::_astore_0; | |
2440 return true; | |
2441 case Bytecodes::_astore: | |
2442 *index = itr->get_index(); | |
2443 return true; | |
2444 } | |
2445 return false; | |
2446 } | |
2447 | |
2448 bool GenerateOopMap::is_aload(BytecodeStream *itr, int *index) { | |
2449 Bytecodes::Code bc = itr->code(); | |
2450 switch(bc) { | |
2451 case Bytecodes::_aload_0: | |
2452 case Bytecodes::_aload_1: | |
2453 case Bytecodes::_aload_2: | |
2454 case Bytecodes::_aload_3: | |
2455 *index = bc - Bytecodes::_aload_0; | |
2456 return true; | |
2457 | |
2458 case Bytecodes::_aload: | |
2459 *index = itr->get_index(); | |
2460 return true; | |
2461 } | |
2462 return false; | |
2463 } | |
2464 | |
2465 | |
2466 // Return true iff the top of the operand stack holds a return address at | |
2467 // the current instruction | |
2468 bool GenerateOopMap::stack_top_holds_ret_addr(int bci) { | |
2469 for(int i = 0; i < _ret_adr_tos->length(); i++) { | |
2470 if (_ret_adr_tos->at(i) == bci) | |
2471 return true; | |
2472 } | |
2473 | |
2474 return false; | |
2475 } | |
2476 | |
2477 void GenerateOopMap::compute_ret_adr_at_TOS() { | |
2478 assert(_ret_adr_tos != NULL, "must be initialized"); | |
2479 _ret_adr_tos->clear(); | |
2480 | |
2481 for (int i = 0; i < bb_count(); i++) { | |
2482 BasicBlock* bb = &_basic_blocks[i]; | |
2483 | |
2484 // Make sure to only check basicblocks that are reachable | |
2485 if (bb->is_reachable()) { | |
2486 | |
2487 // For each Basic block we check all instructions | |
2488 BytecodeStream bcs(_method); | |
2489 bcs.set_interval(bb->_bci, next_bb_start_pc(bb)); | |
2490 | |
2491 restore_state(bb); | |
2492 | |
2493 while (bcs.next()>=0 && !_got_error) { | |
2494 // TDT: should this be is_good_address() ? | |
2495 if (_stack_top > 0 && stack()[_stack_top-1].is_address()) { | |
2496 _ret_adr_tos->append(bcs.bci()); | |
2497 if (TraceNewOopMapGeneration) { | |
2498 tty->print_cr("Ret_adr TOS at bci: %d", bcs.bci()); | |
2499 } | |
2500 } | |
2501 interp1(&bcs); | |
2502 } | |
2503 } | |
2504 } | |
2505 } | |
2506 | |
2507 void GenerateOopMap::update_ret_adr_at_TOS(int bci, int delta) { | |
2508 for(int i = 0; i < _ret_adr_tos->length(); i++) { | |
2509 int v = _ret_adr_tos->at(i); | |
2510 if (v > bci) _ret_adr_tos->at_put(i, v + delta); | |
2511 } | |
2512 } | |
2513 | |
2514 // =================================================================== | |
2515 | |
2516 #ifndef PRODUCT | |
2517 int ResolveOopMapConflicts::_nof_invocations = 0; | |
2518 int ResolveOopMapConflicts::_nof_rewrites = 0; | |
2519 int ResolveOopMapConflicts::_nof_relocations = 0; | |
2520 #endif | |
2521 | |
2522 methodHandle ResolveOopMapConflicts::do_potential_rewrite(TRAPS) { | |
2523 compute_map(CHECK_(methodHandle())); | |
2524 | |
2525 #ifndef PRODUCT | |
2526 // Tracking and statistics | |
2527 if (PrintRewrites) { | |
2528 _nof_invocations++; | |
2529 if (did_rewriting()) { | |
2530 _nof_rewrites++; | |
2531 if (did_relocation()) _nof_relocations++; | |
2532 tty->print("Method was rewritten %s: ", (did_relocation()) ? "and relocated" : ""); | |
2533 method()->print_value(); tty->cr(); | |
2534 tty->print_cr("Cand.: %d rewrts: %d (%d%%) reloc.: %d (%d%%)", | |
2535 _nof_invocations, | |
2536 _nof_rewrites, (_nof_rewrites * 100) / _nof_invocations, | |
2537 _nof_relocations, (_nof_relocations * 100) / _nof_invocations); | |
2538 } | |
2539 } | |
2540 #endif | |
2541 return methodHandle(THREAD, method()); | |
2542 } |