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