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",