src/share/vm/ci/ciMethodBlocks.cpp

changeset 461
0871d5cd64cd
parent 435
a61af66fc99e
child 631
d1605aabd0a1
     1.1 --- a/src/share/vm/ci/ciMethodBlocks.cpp	Wed Feb 20 17:23:43 2008 -0800
     1.2 +++ b/src/share/vm/ci/ciMethodBlocks.cpp	Thu Feb 21 14:03:41 2008 -0800
     1.3 @@ -67,6 +67,14 @@
     1.4        break;
     1.5      }
     1.6    }
     1.7 +  // Move an exception handler information if needed.
     1.8 +  if (former_block->is_handler()) {
     1.9 +    int ex_start = former_block->ex_start_bci();
    1.10 +    int ex_end = former_block->ex_limit_bci();
    1.11 +    new_block->set_exception_range(ex_start, ex_end);
    1.12 +    // Clear information in former_block.
    1.13 +    former_block->clear_exception_handler();
    1.14 +  }
    1.15    return former_block;
    1.16  }
    1.17  
    1.18 @@ -102,7 +110,7 @@
    1.19      // one and end the old one.
    1.20      assert(cur_block != NULL, "must always have a current block");
    1.21      ciBlock *new_block = block_containing(bci);
    1.22 -    if (new_block == NULL) {
    1.23 +    if (new_block == NULL || new_block == cur_block) {
    1.24        // We have not marked this bci as the start of a new block.
    1.25        // Keep interpreting the current_range.
    1.26        _bci_to_block[bci] = cur_block;
    1.27 @@ -254,9 +262,33 @@
    1.28      for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) {
    1.29        ciExceptionHandler* handler = str.handler();
    1.30        ciBlock *eb = make_block_at(handler->handler_bci());
    1.31 -      eb->set_handler();
    1.32 +      //
    1.33 +      // Several exception handlers can have the same handler_bci:
    1.34 +      //
    1.35 +      //  try {
    1.36 +      //    if (a.foo(b) < 0) {
    1.37 +      //      return a.error();
    1.38 +      //    }
    1.39 +      //    return CoderResult.UNDERFLOW;
    1.40 +      //  } finally {
    1.41 +      //      a.position(b);
    1.42 +      //  }
    1.43 +      //
    1.44 +      //  The try block above is divided into 2 exception blocks
    1.45 +      //  separated by 'areturn' bci.
    1.46 +      //
    1.47        int ex_start = handler->start();
    1.48        int ex_end = handler->limit();
    1.49 +      if (eb->is_handler()) {
    1.50 +        // Extend old handler exception range to cover additional range.
    1.51 +        int old_ex_start = eb->ex_start_bci();
    1.52 +        int old_ex_end   = eb->ex_limit_bci();
    1.53 +        if (ex_start > old_ex_start)
    1.54 +          ex_start = old_ex_start;
    1.55 +        if (ex_end < old_ex_end)
    1.56 +          ex_end = old_ex_end;
    1.57 +        eb->clear_exception_handler(); // Reset exception information
    1.58 +      }
    1.59        eb->set_exception_range(ex_start, ex_end);
    1.60        // ensure a block at the start of exception range and start of following code
    1.61        (void) make_block_at(ex_start);
    1.62 @@ -312,9 +344,10 @@
    1.63  
    1.64  void ciBlock::set_exception_range(int start_bci, int limit_bci)  {
    1.65     assert(limit_bci >= start_bci, "valid range");
    1.66 -   assert(is_handler(), "must be handler");
    1.67 +   assert(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1, "must not be handler");
    1.68     _ex_start_bci = start_bci;
    1.69     _ex_limit_bci = limit_bci;
    1.70 +   set_handler();
    1.71  }
    1.72  
    1.73  #ifndef PRODUCT

mercurial