Mercurial > hg > truffle
annotate src/share/vm/ci/ciMethodBlocks.cpp @ 359:d515536da189
6740930: G1: compilation failure with latest gcc
Summary: Include DB fix to resolve a compilation issue with the latest gcc.
Reviewed-by: iveresov, ysr
author | tonyp |
---|---|
date | Tue, 26 Aug 2008 00:46:03 -0400 |
parents | 6ca61c728c2d |
children | 194b8e3a2fc4 |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 2006-2008 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); | |
52 ciBlock *new_block = new(_arena) ciBlock(_method, _num_blocks++, this, former_block->start_bci()); | |
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. | |
86 ciBlock *nb = new(_arena) ciBlock(_method, _num_blocks++, this, bci); | |
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 | |
101 void ciMethodBlocks::do_analysis() { | |
102 ciBytecodeStream s(_method); | |
103 ciBlock *cur_block = block_containing(0); | |
104 int limit_bci = _method->code_size(); | |
105 | |
106 while (s.next() != ciBytecodeStream::EOBC()) { | |
107 int bci = s.cur_bci(); | |
108 // Determine if a new block has been made at the current bci. If | |
109 // this block differs from our current range, switch to the new | |
110 // one and end the old one. | |
111 assert(cur_block != NULL, "must always have a current block"); | |
112 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
|
113 if (new_block == NULL || new_block == cur_block) { |
0 | 114 // We have not marked this bci as the start of a new block. |
115 // Keep interpreting the current_range. | |
116 _bci_to_block[bci] = cur_block; | |
117 } else { | |
118 cur_block->set_limit_bci(bci); | |
119 cur_block = new_block; | |
120 } | |
121 | |
122 switch (s.cur_bc()) { | |
123 case Bytecodes::_ifeq : | |
124 case Bytecodes::_ifne : | |
125 case Bytecodes::_iflt : | |
126 case Bytecodes::_ifge : | |
127 case Bytecodes::_ifgt : | |
128 case Bytecodes::_ifle : | |
129 case Bytecodes::_if_icmpeq : | |
130 case Bytecodes::_if_icmpne : | |
131 case Bytecodes::_if_icmplt : | |
132 case Bytecodes::_if_icmpge : | |
133 case Bytecodes::_if_icmpgt : | |
134 case Bytecodes::_if_icmple : | |
135 case Bytecodes::_if_acmpeq : | |
136 case Bytecodes::_if_acmpne : | |
137 case Bytecodes::_ifnull : | |
138 case Bytecodes::_ifnonnull : | |
139 { | |
140 cur_block->set_control_bci(bci); | |
141 ciBlock *fall_through = make_block_at(s.next_bci()); | |
142 int dest_bci = s.get_dest(); | |
143 ciBlock *dest = make_block_at(dest_bci); | |
144 break; | |
145 } | |
146 | |
147 case Bytecodes::_goto : | |
148 { | |
149 cur_block->set_control_bci(bci); | |
150 if (s.next_bci() < limit_bci) { | |
151 (void) make_block_at(s.next_bci()); | |
152 } | |
153 int dest_bci = s.get_dest(); | |
154 ciBlock *dest = make_block_at(dest_bci); | |
155 break; | |
156 } | |
157 | |
158 case Bytecodes::_jsr : | |
159 { | |
160 cur_block->set_control_bci(bci); | |
161 ciBlock *ret = make_block_at(s.next_bci()); | |
162 int dest_bci = s.get_dest(); | |
163 ciBlock *dest = make_block_at(dest_bci); | |
164 break; | |
165 } | |
166 | |
167 case Bytecodes::_tableswitch : | |
168 { | |
169 cur_block->set_control_bci(bci); | |
170 Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(s.cur_bcp()); | |
171 int len = switch_->length(); | |
172 ciBlock *dest; | |
173 int dest_bci; | |
174 for (int i = 0; i < len; i++) { | |
175 dest_bci = s.cur_bci() + switch_->dest_offset_at(i); | |
176 dest = make_block_at(dest_bci); | |
177 } | |
178 dest_bci = s.cur_bci() + switch_->default_offset(); | |
179 make_block_at(dest_bci); | |
180 if (s.next_bci() < limit_bci) { | |
181 dest = make_block_at(s.next_bci()); | |
182 } | |
183 } | |
184 break; | |
185 | |
186 case Bytecodes::_lookupswitch: | |
187 { | |
188 cur_block->set_control_bci(bci); | |
189 Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(s.cur_bcp()); | |
190 int len = switch_->number_of_pairs(); | |
191 ciBlock *dest; | |
192 int dest_bci; | |
193 for (int i = 0; i < len; i++) { | |
194 dest_bci = s.cur_bci() + switch_->pair_at(i)->offset(); | |
195 dest = make_block_at(dest_bci); | |
196 } | |
197 dest_bci = s.cur_bci() + switch_->default_offset(); | |
198 dest = make_block_at(dest_bci); | |
199 if (s.next_bci() < limit_bci) { | |
200 dest = make_block_at(s.next_bci()); | |
201 } | |
202 } | |
203 break; | |
204 | |
205 case Bytecodes::_goto_w : | |
206 { | |
207 cur_block->set_control_bci(bci); | |
208 if (s.next_bci() < limit_bci) { | |
209 (void) make_block_at(s.next_bci()); | |
210 } | |
211 int dest_bci = s.get_far_dest(); | |
212 ciBlock *dest = make_block_at(dest_bci); | |
213 break; | |
214 } | |
215 | |
216 case Bytecodes::_jsr_w : | |
217 { | |
218 cur_block->set_control_bci(bci); | |
219 ciBlock *ret = make_block_at(s.next_bci()); | |
220 int dest_bci = s.get_far_dest(); | |
221 ciBlock *dest = make_block_at(dest_bci); | |
222 break; | |
223 } | |
224 | |
225 case Bytecodes::_athrow : | |
226 cur_block->set_may_throw(); | |
227 // fall-through | |
228 case Bytecodes::_ret : | |
229 case Bytecodes::_ireturn : | |
230 case Bytecodes::_lreturn : | |
231 case Bytecodes::_freturn : | |
232 case Bytecodes::_dreturn : | |
233 case Bytecodes::_areturn : | |
234 case Bytecodes::_return : | |
235 cur_block->set_control_bci(bci); | |
236 if (s.next_bci() < limit_bci) { | |
237 (void) make_block_at(s.next_bci()); | |
238 } | |
239 break; | |
240 } | |
241 } | |
242 // End the last block | |
243 cur_block->set_limit_bci(limit_bci); | |
244 } | |
245 | |
246 ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth), | |
247 _arena(arena), _num_blocks(0), _code_size(meth->code_size()) { | |
248 int block_estimate = _code_size / 8; | |
249 | |
250 _blocks = new(_arena) GrowableArray<ciBlock *>(block_estimate); | |
251 int b2bsize = _code_size * sizeof(ciBlock **); | |
252 _bci_to_block = (ciBlock **) arena->Amalloc(b2bsize); | |
253 Copy::zero_to_words((HeapWord*) _bci_to_block, b2bsize / sizeof(HeapWord)); | |
254 | |
255 // create initial block covering the entire method | |
256 ciBlock *b = new(arena) ciBlock(_method, _num_blocks++, this, 0); | |
257 _blocks->append(b); | |
258 _bci_to_block[0] = b; | |
259 | |
260 // create blocks for exception handlers | |
261 if (meth->has_exception_handlers()) { | |
262 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | |
263 ciExceptionHandler* handler = str.handler(); | |
264 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
|
265 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
266 // 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
|
267 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
268 // try { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
269 // if (a.foo(b) < 0) { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
270 // return a.error(); |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
271 // } |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
272 // return CoderResult.UNDERFLOW; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
273 // } finally { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
274 // a.position(b); |
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 // |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
277 // 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
|
278 // separated by 'areturn' bci. |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
279 // |
0 | 280 int ex_start = handler->start(); |
281 int ex_end = handler->limit(); | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
282 if (eb->is_handler()) { |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
283 // 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
|
284 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
|
285 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
|
286 if (ex_start > old_ex_start) |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
287 ex_start = old_ex_start; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
288 if (ex_end < old_ex_end) |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
289 ex_end = old_ex_end; |
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
290 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
|
291 } |
0 | 292 eb->set_exception_range(ex_start, ex_end); |
293 // ensure a block at the start of exception range and start of following code | |
294 (void) make_block_at(ex_start); | |
295 if (ex_end < _code_size) | |
296 (void) make_block_at(ex_end); | |
297 } | |
298 } | |
299 | |
300 // scan the bytecodes and identify blocks | |
301 do_analysis(); | |
302 | |
303 // mark blocks that have exception handlers | |
304 if (meth->has_exception_handlers()) { | |
305 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | |
306 ciExceptionHandler* handler = str.handler(); | |
307 int ex_start = handler->start(); | |
308 int ex_end = handler->limit(); | |
309 | |
310 int bci = ex_start; | |
311 while (bci < ex_end) { | |
312 ciBlock *b = block_containing(bci); | |
313 b->set_has_handler(); | |
314 bci = b->limit_bci(); | |
315 } | |
316 } | |
317 } | |
318 } | |
319 | |
320 void ciMethodBlocks::clear_processed() { | |
321 for (int i = 0; i < _blocks->length(); i++) | |
322 _blocks->at(i)->clear_processed(); | |
323 } | |
324 | |
325 #ifndef PRODUCT | |
326 void ciMethodBlocks::dump() { | |
327 tty->print("---- blocks for method: "); | |
328 _method->print(); | |
329 tty->cr(); | |
330 for (int i = 0; i < _blocks->length(); i++) { | |
331 tty->print(" B%d: ", i); _blocks->at(i)->dump(); | |
332 } | |
333 } | |
334 #endif | |
335 | |
336 | |
337 ciBlock::ciBlock(ciMethod *method, int index, ciMethodBlocks *mb, int start_bci) : | |
338 #ifndef PRODUCT | |
339 _method(method), | |
340 #endif | |
341 _idx(index), _flags(0), _start_bci(start_bci), _limit_bci(-1), _control_bci(fall_through_bci), | |
342 _ex_start_bci(-1), _ex_limit_bci(-1) { | |
343 } | |
344 | |
345 void ciBlock::set_exception_range(int start_bci, int limit_bci) { | |
346 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
|
347 assert(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1, "must not be handler"); |
0 | 348 _ex_start_bci = start_bci; |
349 _ex_limit_bci = limit_bci; | |
26
0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
kvn
parents:
0
diff
changeset
|
350 set_handler(); |
0 | 351 } |
352 | |
353 #ifndef PRODUCT | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
196
diff
changeset
|
354 static const char *flagnames[] = { |
0 | 355 "Processed", |
356 "Handler", | |
357 "MayThrow", | |
358 "Jsr", | |
359 "Ret", | |
360 "RetTarget", | |
361 "HasHandler", | |
362 }; | |
363 | |
364 void ciBlock::dump() { | |
365 tty->print(" [%d .. %d), {", _start_bci, _limit_bci); | |
366 for (int i = 0; i < 8; i++) { | |
367 if ((_flags & (1 << i)) != 0) { | |
368 tty->print(" %s", flagnames[i]); | |
369 } | |
370 } | |
371 tty->print(" ]"); | |
372 if (is_handler()) | |
373 tty->print(" handles(%d..%d)", _ex_start_bci, _ex_limit_bci); | |
374 tty->cr(); | |
375 } | |
376 | |
377 // ------------------------------------------------------------------ | |
378 // ciBlock::print_on | |
379 void ciBlock::print_on(outputStream* st) const { | |
380 st->print_cr("--------------------------------------------------------"); | |
381 st->print ("ciBlock [%d - %d) control : ", start_bci(), limit_bci()); | |
382 if (control_bci() == fall_through_bci) { | |
383 st->print_cr("%d:fall through", limit_bci()); | |
384 } else { | |
385 st->print_cr("%d:%s", control_bci(), | |
386 Bytecodes::name(method()->java_code_at_bci(control_bci()))); | |
387 } | |
388 | |
389 if (Verbose || WizardMode) { | |
390 method()->print_codes_on(start_bci(), limit_bci(), st); | |
391 } | |
392 } | |
393 #endif |