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