Mercurial > hg > truffle
annotate src/share/vm/ci/ciMethodBlocks.cpp @ 14680:2dfa56e10640
8027124: [TESTBUG] NonTieredLevelsTest: java.lang.RuntimeException: private TestCase$Helper(java.lang.Object) must be osr_compiled
Reviewed-by: kvn, roland
author | iignatyev |
---|---|
date | Thu, 06 Mar 2014 12:47:45 +0400 |
parents | 8012aa3ccede |
children |
rev | line source |
---|---|
0 | 1 /* |
2142 | 2 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
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:
844
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "ci/ciMethodBlocks.hpp" | |
27 #include "ci/ciStreams.hpp" | |
28 #include "interpreter/bytecode.hpp" | |
29 #include "utilities/copy.hpp" | |
0 | 30 |
31 // ciMethodBlocks | |
32 | |
33 | |
34 | |
35 ciBlock *ciMethodBlocks::block_containing(int bci) { | |
36 ciBlock *blk = _bci_to_block[bci]; | |
37 return blk; | |
38 } | |
39 | |
40 bool ciMethodBlocks::is_block_start(int bci) { | |
41 assert(bci >=0 && bci < _code_size, "valid bytecode range"); | |
42 ciBlock *b = _bci_to_block[bci]; | |
43 assert(b != NULL, "must have block for bytecode"); | |
44 return b->start_bci() == bci; | |
45 } | |
46 | |
47 // ------------------------------------------------------------------ | |
48 // ciMethodBlocks::split_block_at | |
49 // | |
50 // Split the block spanning bci into two separate ranges. The former | |
51 // block becomes the second half and a new range is created for the | |
52 // first half. Returns the range beginning at bci. | |
53 ciBlock *ciMethodBlocks::split_block_at(int bci) { | |
54 ciBlock *former_block = block_containing(bci); | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
55 ciBlock *new_block = new(_arena) ciBlock(_method, _num_blocks++, former_block->start_bci()); |
0 | 56 _blocks->append(new_block); |
57 assert(former_block != NULL, "must not be NULL"); | |
58 new_block->set_limit_bci(bci); | |
59 former_block->set_start_bci(bci); | |
60 for (int pos=bci-1; pos >= 0; pos--) { | |
61 ciBlock *current_block = block_containing(pos); | |
62 if (current_block == former_block) { | |
63 // Replace it. | |
64 _bci_to_block[pos] = new_block; | |
65 } else if (current_block == NULL) { | |
66 // Non-bytecode start. Skip. | |
67 continue; | |
68 } else { | |
69 // We are done with our backwards walk | |
70 break; | |
71 } | |
72 } | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
73 // Move an exception handler information if needed. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
74 if (former_block->is_handler()) { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
75 int ex_start = former_block->ex_start_bci(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
76 int ex_end = former_block->ex_limit_bci(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
77 new_block->set_exception_range(ex_start, ex_end); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
78 // Clear information in former_block. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
79 former_block->clear_exception_handler(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
80 } |
0 | 81 return former_block; |
82 } | |
83 | |
84 ciBlock *ciMethodBlocks::make_block_at(int bci) { | |
85 ciBlock *cb = block_containing(bci); | |
86 if (cb == NULL ) { | |
87 // This is our first time visiting this bytecode. Create | |
88 // a fresh block and assign it this starting point. | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
89 ciBlock *nb = new(_arena) ciBlock(_method, _num_blocks++, bci); |
0 | 90 _blocks->append(nb); |
91 _bci_to_block[bci] = nb; | |
92 return nb; | |
93 } else if (cb->start_bci() == bci) { | |
94 // The block begins at bci. Simply return it. | |
95 return cb; | |
96 } else { | |
97 // We have already created a block containing bci but | |
98 // not starting at bci. This existing block needs to | |
99 // be split into two. | |
100 return split_block_at(bci); | |
101 } | |
102 } | |
103 | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
104 ciBlock *ciMethodBlocks::make_dummy_block() { |
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
105 ciBlock *dum = new(_arena) ciBlock(_method, -1, 0); |
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
106 return dum; |
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
107 } |
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
108 |
0 | 109 void ciMethodBlocks::do_analysis() { |
110 ciBytecodeStream s(_method); | |
111 ciBlock *cur_block = block_containing(0); | |
112 int limit_bci = _method->code_size(); | |
113 | |
114 while (s.next() != ciBytecodeStream::EOBC()) { | |
115 int bci = s.cur_bci(); | |
116 // Determine if a new block has been made at the current bci. If | |
117 // this block differs from our current range, switch to the new | |
118 // one and end the old one. | |
119 assert(cur_block != NULL, "must always have a current block"); | |
120 ciBlock *new_block = block_containing(bci); | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
121 if (new_block == NULL || new_block == cur_block) { |
0 | 122 // We have not marked this bci as the start of a new block. |
123 // Keep interpreting the current_range. | |
124 _bci_to_block[bci] = cur_block; | |
125 } else { | |
126 cur_block->set_limit_bci(bci); | |
127 cur_block = new_block; | |
128 } | |
129 | |
130 switch (s.cur_bc()) { | |
131 case Bytecodes::_ifeq : | |
132 case Bytecodes::_ifne : | |
133 case Bytecodes::_iflt : | |
134 case Bytecodes::_ifge : | |
135 case Bytecodes::_ifgt : | |
136 case Bytecodes::_ifle : | |
137 case Bytecodes::_if_icmpeq : | |
138 case Bytecodes::_if_icmpne : | |
139 case Bytecodes::_if_icmplt : | |
140 case Bytecodes::_if_icmpge : | |
141 case Bytecodes::_if_icmpgt : | |
142 case Bytecodes::_if_icmple : | |
143 case Bytecodes::_if_acmpeq : | |
144 case Bytecodes::_if_acmpne : | |
145 case Bytecodes::_ifnull : | |
146 case Bytecodes::_ifnonnull : | |
147 { | |
148 cur_block->set_control_bci(bci); | |
149 ciBlock *fall_through = make_block_at(s.next_bci()); | |
150 int dest_bci = s.get_dest(); | |
151 ciBlock *dest = make_block_at(dest_bci); | |
152 break; | |
153 } | |
154 | |
155 case Bytecodes::_goto : | |
156 { | |
157 cur_block->set_control_bci(bci); | |
158 if (s.next_bci() < limit_bci) { | |
159 (void) make_block_at(s.next_bci()); | |
160 } | |
161 int dest_bci = s.get_dest(); | |
162 ciBlock *dest = make_block_at(dest_bci); | |
163 break; | |
164 } | |
165 | |
166 case Bytecodes::_jsr : | |
167 { | |
168 cur_block->set_control_bci(bci); | |
169 ciBlock *ret = make_block_at(s.next_bci()); | |
170 int dest_bci = s.get_dest(); | |
171 ciBlock *dest = make_block_at(dest_bci); | |
172 break; | |
173 } | |
174 | |
175 case Bytecodes::_tableswitch : | |
176 { | |
177 cur_block->set_control_bci(bci); | |
2142 | 178 Bytecode_tableswitch sw(&s); |
179 int len = sw.length(); | |
0 | 180 ciBlock *dest; |
181 int dest_bci; | |
182 for (int i = 0; i < len; i++) { | |
2142 | 183 dest_bci = s.cur_bci() + sw.dest_offset_at(i); |
0 | 184 dest = make_block_at(dest_bci); |
185 } | |
2142 | 186 dest_bci = s.cur_bci() + sw.default_offset(); |
0 | 187 make_block_at(dest_bci); |
188 if (s.next_bci() < limit_bci) { | |
189 dest = make_block_at(s.next_bci()); | |
190 } | |
191 } | |
192 break; | |
193 | |
194 case Bytecodes::_lookupswitch: | |
195 { | |
196 cur_block->set_control_bci(bci); | |
2142 | 197 Bytecode_lookupswitch sw(&s); |
198 int len = sw.number_of_pairs(); | |
0 | 199 ciBlock *dest; |
200 int dest_bci; | |
201 for (int i = 0; i < len; i++) { | |
2142 | 202 dest_bci = s.cur_bci() + sw.pair_at(i).offset(); |
0 | 203 dest = make_block_at(dest_bci); |
204 } | |
2142 | 205 dest_bci = s.cur_bci() + sw.default_offset(); |
0 | 206 dest = make_block_at(dest_bci); |
207 if (s.next_bci() < limit_bci) { | |
208 dest = make_block_at(s.next_bci()); | |
209 } | |
210 } | |
211 break; | |
212 | |
213 case Bytecodes::_goto_w : | |
214 { | |
215 cur_block->set_control_bci(bci); | |
216 if (s.next_bci() < limit_bci) { | |
217 (void) make_block_at(s.next_bci()); | |
218 } | |
219 int dest_bci = s.get_far_dest(); | |
220 ciBlock *dest = make_block_at(dest_bci); | |
221 break; | |
222 } | |
223 | |
224 case Bytecodes::_jsr_w : | |
225 { | |
226 cur_block->set_control_bci(bci); | |
227 ciBlock *ret = make_block_at(s.next_bci()); | |
228 int dest_bci = s.get_far_dest(); | |
229 ciBlock *dest = make_block_at(dest_bci); | |
230 break; | |
231 } | |
232 | |
233 case Bytecodes::_athrow : | |
234 cur_block->set_may_throw(); | |
235 // fall-through | |
236 case Bytecodes::_ret : | |
237 case Bytecodes::_ireturn : | |
238 case Bytecodes::_lreturn : | |
239 case Bytecodes::_freturn : | |
240 case Bytecodes::_dreturn : | |
241 case Bytecodes::_areturn : | |
242 case Bytecodes::_return : | |
243 cur_block->set_control_bci(bci); | |
244 if (s.next_bci() < limit_bci) { | |
245 (void) make_block_at(s.next_bci()); | |
246 } | |
247 break; | |
248 } | |
249 } | |
250 // End the last block | |
251 cur_block->set_limit_bci(limit_bci); | |
252 } | |
253 | |
254 ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth), | |
255 _arena(arena), _num_blocks(0), _code_size(meth->code_size()) { | |
256 int block_estimate = _code_size / 8; | |
257 | |
1685 | 258 _blocks = new(_arena) GrowableArray<ciBlock *>(_arena, block_estimate, 0, NULL); |
0 | 259 int b2bsize = _code_size * sizeof(ciBlock **); |
260 _bci_to_block = (ciBlock **) arena->Amalloc(b2bsize); | |
261 Copy::zero_to_words((HeapWord*) _bci_to_block, b2bsize / sizeof(HeapWord)); | |
262 | |
263 // create initial block covering the entire method | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
264 ciBlock *b = new(arena) ciBlock(_method, _num_blocks++, 0); |
0 | 265 _blocks->append(b); |
266 _bci_to_block[0] = b; | |
267 | |
268 // create blocks for exception handlers | |
269 if (meth->has_exception_handlers()) { | |
270 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | |
271 ciExceptionHandler* handler = str.handler(); | |
272 ciBlock *eb = make_block_at(handler->handler_bci()); | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
273 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
274 // Several exception handlers can have the same handler_bci: |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
275 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
276 // try { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
277 // if (a.foo(b) < 0) { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
278 // return a.error(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
279 // } |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
280 // return CoderResult.UNDERFLOW; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
281 // } finally { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
282 // a.position(b); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
283 // } |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
284 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
285 // The try block above is divided into 2 exception blocks |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
286 // separated by 'areturn' bci. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
287 // |
0 | 288 int ex_start = handler->start(); |
289 int ex_end = handler->limit(); | |
646 | 290 // ensure a block at the start of exception range and start of following code |
291 (void) make_block_at(ex_start); | |
292 if (ex_end < _code_size) | |
293 (void) make_block_at(ex_end); | |
294 | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
295 if (eb->is_handler()) { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
296 // Extend old handler exception range to cover additional range. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
297 int old_ex_start = eb->ex_start_bci(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
298 int old_ex_end = eb->ex_limit_bci(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
299 if (ex_start > old_ex_start) |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
300 ex_start = old_ex_start; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
301 if (ex_end < old_ex_end) |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
302 ex_end = old_ex_end; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
303 eb->clear_exception_handler(); // Reset exception information |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
304 } |
0 | 305 eb->set_exception_range(ex_start, ex_end); |
306 } | |
307 } | |
308 | |
309 // scan the bytecodes and identify blocks | |
310 do_analysis(); | |
311 | |
312 // mark blocks that have exception handlers | |
313 if (meth->has_exception_handlers()) { | |
314 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | |
315 ciExceptionHandler* handler = str.handler(); | |
316 int ex_start = handler->start(); | |
317 int ex_end = handler->limit(); | |
318 | |
319 int bci = ex_start; | |
320 while (bci < ex_end) { | |
321 ciBlock *b = block_containing(bci); | |
322 b->set_has_handler(); | |
323 bci = b->limit_bci(); | |
324 } | |
325 } | |
326 } | |
327 } | |
328 | |
329 void ciMethodBlocks::clear_processed() { | |
330 for (int i = 0; i < _blocks->length(); i++) | |
331 _blocks->at(i)->clear_processed(); | |
332 } | |
333 | |
334 #ifndef PRODUCT | |
335 void ciMethodBlocks::dump() { | |
336 tty->print("---- blocks for method: "); | |
337 _method->print(); | |
338 tty->cr(); | |
339 for (int i = 0; i < _blocks->length(); i++) { | |
340 tty->print(" B%d: ", i); _blocks->at(i)->dump(); | |
341 } | |
342 } | |
343 #endif | |
344 | |
345 | |
367
194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents:
250
diff
changeset
|
346 ciBlock::ciBlock(ciMethod *method, int index, int start_bci) : |
0 | 347 #ifndef PRODUCT |
348 _method(method), | |
349 #endif | |
350 _idx(index), _flags(0), _start_bci(start_bci), _limit_bci(-1), _control_bci(fall_through_bci), | |
351 _ex_start_bci(-1), _ex_limit_bci(-1) { | |
352 } | |
353 | |
354 void ciBlock::set_exception_range(int start_bci, int limit_bci) { | |
355 assert(limit_bci >= start_bci, "valid range"); | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
356 assert(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1, "must not be handler"); |
0 | 357 _ex_start_bci = start_bci; |
358 _ex_limit_bci = limit_bci; | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
359 set_handler(); |
0 | 360 } |
361 | |
362 #ifndef PRODUCT | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
196
diff
changeset
|
363 static const char *flagnames[] = { |
0 | 364 "Processed", |
365 "Handler", | |
366 "MayThrow", | |
367 "Jsr", | |
368 "Ret", | |
369 "RetTarget", | |
370 "HasHandler", | |
371 }; | |
372 | |
373 void ciBlock::dump() { | |
374 tty->print(" [%d .. %d), {", _start_bci, _limit_bci); | |
375 for (int i = 0; i < 8; i++) { | |
376 if ((_flags & (1 << i)) != 0) { | |
377 tty->print(" %s", flagnames[i]); | |
378 } | |
379 } | |
380 tty->print(" ]"); | |
381 if (is_handler()) | |
382 tty->print(" handles(%d..%d)", _ex_start_bci, _ex_limit_bci); | |
383 tty->cr(); | |
384 } | |
385 | |
386 // ------------------------------------------------------------------ | |
387 // ciBlock::print_on | |
388 void ciBlock::print_on(outputStream* st) const { | |
389 st->print_cr("--------------------------------------------------------"); | |
390 st->print ("ciBlock [%d - %d) control : ", start_bci(), limit_bci()); | |
391 if (control_bci() == fall_through_bci) { | |
392 st->print_cr("%d:fall through", limit_bci()); | |
393 } else { | |
394 st->print_cr("%d:%s", control_bci(), | |
395 Bytecodes::name(method()->java_code_at_bci(control_bci()))); | |
396 } | |
397 | |
398 if (Verbose || WizardMode) { | |
399 method()->print_codes_on(start_bci(), limit_bci(), st); | |
400 } | |
401 } | |
402 #endif |