Mercurial > hg > truffle
comparison src/share/vm/ci/ciMethodBlocks.cpp @ 26:0871d5cd64cd
6621084: ciMethodBlocks::split_block_at() is broken for methods with exception handler
Summary: After an exception handler block is split the exception information is not moved to the new block which starts in exception handler BCI.
Reviewed-by: jrose
author | kvn |
---|---|
date | Thu, 21 Feb 2008 14:03:41 -0800 |
parents | a61af66fc99e |
children | d1605aabd0a1 |
comparison
equal
deleted
inserted
replaced
25:c5cbd367e4d1 | 26:0871d5cd64cd |
---|---|
65 } else { | 65 } else { |
66 // We are done with our backwards walk | 66 // We are done with our backwards walk |
67 break; | 67 break; |
68 } | 68 } |
69 } | 69 } |
70 // Move an exception handler information if needed. | |
71 if (former_block->is_handler()) { | |
72 int ex_start = former_block->ex_start_bci(); | |
73 int ex_end = former_block->ex_limit_bci(); | |
74 new_block->set_exception_range(ex_start, ex_end); | |
75 // Clear information in former_block. | |
76 former_block->clear_exception_handler(); | |
77 } | |
70 return former_block; | 78 return former_block; |
71 } | 79 } |
72 | 80 |
73 ciBlock *ciMethodBlocks::make_block_at(int bci) { | 81 ciBlock *ciMethodBlocks::make_block_at(int bci) { |
74 ciBlock *cb = block_containing(bci); | 82 ciBlock *cb = block_containing(bci); |
100 // Determine if a new block has been made at the current bci. If | 108 // Determine if a new block has been made at the current bci. If |
101 // this block differs from our current range, switch to the new | 109 // this block differs from our current range, switch to the new |
102 // one and end the old one. | 110 // one and end the old one. |
103 assert(cur_block != NULL, "must always have a current block"); | 111 assert(cur_block != NULL, "must always have a current block"); |
104 ciBlock *new_block = block_containing(bci); | 112 ciBlock *new_block = block_containing(bci); |
105 if (new_block == NULL) { | 113 if (new_block == NULL || new_block == cur_block) { |
106 // We have not marked this bci as the start of a new block. | 114 // We have not marked this bci as the start of a new block. |
107 // Keep interpreting the current_range. | 115 // Keep interpreting the current_range. |
108 _bci_to_block[bci] = cur_block; | 116 _bci_to_block[bci] = cur_block; |
109 } else { | 117 } else { |
110 cur_block->set_limit_bci(bci); | 118 cur_block->set_limit_bci(bci); |
252 // create blocks for exception handlers | 260 // create blocks for exception handlers |
253 if (meth->has_exception_handlers()) { | 261 if (meth->has_exception_handlers()) { |
254 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { | 262 for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { |
255 ciExceptionHandler* handler = str.handler(); | 263 ciExceptionHandler* handler = str.handler(); |
256 ciBlock *eb = make_block_at(handler->handler_bci()); | 264 ciBlock *eb = make_block_at(handler->handler_bci()); |
257 eb->set_handler(); | 265 // |
266 // Several exception handlers can have the same handler_bci: | |
267 // | |
268 // try { | |
269 // if (a.foo(b) < 0) { | |
270 // return a.error(); | |
271 // } | |
272 // return CoderResult.UNDERFLOW; | |
273 // } finally { | |
274 // a.position(b); | |
275 // } | |
276 // | |
277 // The try block above is divided into 2 exception blocks | |
278 // separated by 'areturn' bci. | |
279 // | |
258 int ex_start = handler->start(); | 280 int ex_start = handler->start(); |
259 int ex_end = handler->limit(); | 281 int ex_end = handler->limit(); |
282 if (eb->is_handler()) { | |
283 // Extend old handler exception range to cover additional range. | |
284 int old_ex_start = eb->ex_start_bci(); | |
285 int old_ex_end = eb->ex_limit_bci(); | |
286 if (ex_start > old_ex_start) | |
287 ex_start = old_ex_start; | |
288 if (ex_end < old_ex_end) | |
289 ex_end = old_ex_end; | |
290 eb->clear_exception_handler(); // Reset exception information | |
291 } | |
260 eb->set_exception_range(ex_start, ex_end); | 292 eb->set_exception_range(ex_start, ex_end); |
261 // ensure a block at the start of exception range and start of following code | 293 // ensure a block at the start of exception range and start of following code |
262 (void) make_block_at(ex_start); | 294 (void) make_block_at(ex_start); |
263 if (ex_end < _code_size) | 295 if (ex_end < _code_size) |
264 (void) make_block_at(ex_end); | 296 (void) make_block_at(ex_end); |
310 _ex_start_bci(-1), _ex_limit_bci(-1) { | 342 _ex_start_bci(-1), _ex_limit_bci(-1) { |
311 } | 343 } |
312 | 344 |
313 void ciBlock::set_exception_range(int start_bci, int limit_bci) { | 345 void ciBlock::set_exception_range(int start_bci, int limit_bci) { |
314 assert(limit_bci >= start_bci, "valid range"); | 346 assert(limit_bci >= start_bci, "valid range"); |
315 assert(is_handler(), "must be handler"); | 347 assert(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1, "must not be handler"); |
316 _ex_start_bci = start_bci; | 348 _ex_start_bci = start_bci; |
317 _ex_limit_bci = limit_bci; | 349 _ex_limit_bci = limit_bci; |
350 set_handler(); | |
318 } | 351 } |
319 | 352 |
320 #ifndef PRODUCT | 353 #ifndef PRODUCT |
321 static char *flagnames[] = { | 354 static char *flagnames[] = { |
322 "Processed", | 355 "Processed", |