1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/ci/ciMethodBlocks.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,360 @@ 1.4 +/* 1.5 + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "incls/_precompiled.incl" 1.29 +#include "incls/_ciMethodBlocks.cpp.incl" 1.30 + 1.31 +// ciMethodBlocks 1.32 + 1.33 + 1.34 + 1.35 +ciBlock *ciMethodBlocks::block_containing(int bci) { 1.36 + ciBlock *blk = _bci_to_block[bci]; 1.37 + return blk; 1.38 +} 1.39 + 1.40 +bool ciMethodBlocks::is_block_start(int bci) { 1.41 + assert(bci >=0 && bci < _code_size, "valid bytecode range"); 1.42 + ciBlock *b = _bci_to_block[bci]; 1.43 + assert(b != NULL, "must have block for bytecode"); 1.44 + return b->start_bci() == bci; 1.45 +} 1.46 + 1.47 +// ------------------------------------------------------------------ 1.48 +// ciMethodBlocks::split_block_at 1.49 +// 1.50 +// Split the block spanning bci into two separate ranges. The former 1.51 +// block becomes the second half and a new range is created for the 1.52 +// first half. Returns the range beginning at bci. 1.53 +ciBlock *ciMethodBlocks::split_block_at(int bci) { 1.54 + ciBlock *former_block = block_containing(bci); 1.55 + ciBlock *new_block = new(_arena) ciBlock(_method, _num_blocks++, this, former_block->start_bci()); 1.56 + _blocks->append(new_block); 1.57 + assert(former_block != NULL, "must not be NULL"); 1.58 + new_block->set_limit_bci(bci); 1.59 + former_block->set_start_bci(bci); 1.60 + for (int pos=bci-1; pos >= 0; pos--) { 1.61 + ciBlock *current_block = block_containing(pos); 1.62 + if (current_block == former_block) { 1.63 + // Replace it. 1.64 + _bci_to_block[pos] = new_block; 1.65 + } else if (current_block == NULL) { 1.66 + // Non-bytecode start. Skip. 1.67 + continue; 1.68 + } else { 1.69 + // We are done with our backwards walk 1.70 + break; 1.71 + } 1.72 + } 1.73 + return former_block; 1.74 +} 1.75 + 1.76 +ciBlock *ciMethodBlocks::make_block_at(int bci) { 1.77 + ciBlock *cb = block_containing(bci); 1.78 + if (cb == NULL ) { 1.79 + // This is our first time visiting this bytecode. Create 1.80 + // a fresh block and assign it this starting point. 1.81 + ciBlock *nb = new(_arena) ciBlock(_method, _num_blocks++, this, bci); 1.82 + _blocks->append(nb); 1.83 + _bci_to_block[bci] = nb; 1.84 + return nb; 1.85 + } else if (cb->start_bci() == bci) { 1.86 + // The block begins at bci. Simply return it. 1.87 + return cb; 1.88 + } else { 1.89 + // We have already created a block containing bci but 1.90 + // not starting at bci. This existing block needs to 1.91 + // be split into two. 1.92 + return split_block_at(bci); 1.93 + } 1.94 +} 1.95 + 1.96 +void ciMethodBlocks::do_analysis() { 1.97 + ciBytecodeStream s(_method); 1.98 + ciBlock *cur_block = block_containing(0); 1.99 + int limit_bci = _method->code_size(); 1.100 + 1.101 + while (s.next() != ciBytecodeStream::EOBC()) { 1.102 + int bci = s.cur_bci(); 1.103 + // Determine if a new block has been made at the current bci. If 1.104 + // this block differs from our current range, switch to the new 1.105 + // one and end the old one. 1.106 + assert(cur_block != NULL, "must always have a current block"); 1.107 + ciBlock *new_block = block_containing(bci); 1.108 + if (new_block == NULL) { 1.109 + // We have not marked this bci as the start of a new block. 1.110 + // Keep interpreting the current_range. 1.111 + _bci_to_block[bci] = cur_block; 1.112 + } else { 1.113 + cur_block->set_limit_bci(bci); 1.114 + cur_block = new_block; 1.115 + } 1.116 + 1.117 + switch (s.cur_bc()) { 1.118 + case Bytecodes::_ifeq : 1.119 + case Bytecodes::_ifne : 1.120 + case Bytecodes::_iflt : 1.121 + case Bytecodes::_ifge : 1.122 + case Bytecodes::_ifgt : 1.123 + case Bytecodes::_ifle : 1.124 + case Bytecodes::_if_icmpeq : 1.125 + case Bytecodes::_if_icmpne : 1.126 + case Bytecodes::_if_icmplt : 1.127 + case Bytecodes::_if_icmpge : 1.128 + case Bytecodes::_if_icmpgt : 1.129 + case Bytecodes::_if_icmple : 1.130 + case Bytecodes::_if_acmpeq : 1.131 + case Bytecodes::_if_acmpne : 1.132 + case Bytecodes::_ifnull : 1.133 + case Bytecodes::_ifnonnull : 1.134 + { 1.135 + cur_block->set_control_bci(bci); 1.136 + ciBlock *fall_through = make_block_at(s.next_bci()); 1.137 + int dest_bci = s.get_dest(); 1.138 + ciBlock *dest = make_block_at(dest_bci); 1.139 + break; 1.140 + } 1.141 + 1.142 + case Bytecodes::_goto : 1.143 + { 1.144 + cur_block->set_control_bci(bci); 1.145 + if (s.next_bci() < limit_bci) { 1.146 + (void) make_block_at(s.next_bci()); 1.147 + } 1.148 + int dest_bci = s.get_dest(); 1.149 + ciBlock *dest = make_block_at(dest_bci); 1.150 + break; 1.151 + } 1.152 + 1.153 + case Bytecodes::_jsr : 1.154 + { 1.155 + cur_block->set_control_bci(bci); 1.156 + ciBlock *ret = make_block_at(s.next_bci()); 1.157 + int dest_bci = s.get_dest(); 1.158 + ciBlock *dest = make_block_at(dest_bci); 1.159 + break; 1.160 + } 1.161 + 1.162 + case Bytecodes::_tableswitch : 1.163 + { 1.164 + cur_block->set_control_bci(bci); 1.165 + Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(s.cur_bcp()); 1.166 + int len = switch_->length(); 1.167 + ciBlock *dest; 1.168 + int dest_bci; 1.169 + for (int i = 0; i < len; i++) { 1.170 + dest_bci = s.cur_bci() + switch_->dest_offset_at(i); 1.171 + dest = make_block_at(dest_bci); 1.172 + } 1.173 + dest_bci = s.cur_bci() + switch_->default_offset(); 1.174 + make_block_at(dest_bci); 1.175 + if (s.next_bci() < limit_bci) { 1.176 + dest = make_block_at(s.next_bci()); 1.177 + } 1.178 + } 1.179 + break; 1.180 + 1.181 + case Bytecodes::_lookupswitch: 1.182 + { 1.183 + cur_block->set_control_bci(bci); 1.184 + Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(s.cur_bcp()); 1.185 + int len = switch_->number_of_pairs(); 1.186 + ciBlock *dest; 1.187 + int dest_bci; 1.188 + for (int i = 0; i < len; i++) { 1.189 + dest_bci = s.cur_bci() + switch_->pair_at(i)->offset(); 1.190 + dest = make_block_at(dest_bci); 1.191 + } 1.192 + dest_bci = s.cur_bci() + switch_->default_offset(); 1.193 + dest = make_block_at(dest_bci); 1.194 + if (s.next_bci() < limit_bci) { 1.195 + dest = make_block_at(s.next_bci()); 1.196 + } 1.197 + } 1.198 + break; 1.199 + 1.200 + case Bytecodes::_goto_w : 1.201 + { 1.202 + cur_block->set_control_bci(bci); 1.203 + if (s.next_bci() < limit_bci) { 1.204 + (void) make_block_at(s.next_bci()); 1.205 + } 1.206 + int dest_bci = s.get_far_dest(); 1.207 + ciBlock *dest = make_block_at(dest_bci); 1.208 + break; 1.209 + } 1.210 + 1.211 + case Bytecodes::_jsr_w : 1.212 + { 1.213 + cur_block->set_control_bci(bci); 1.214 + ciBlock *ret = make_block_at(s.next_bci()); 1.215 + int dest_bci = s.get_far_dest(); 1.216 + ciBlock *dest = make_block_at(dest_bci); 1.217 + break; 1.218 + } 1.219 + 1.220 + case Bytecodes::_athrow : 1.221 + cur_block->set_may_throw(); 1.222 + // fall-through 1.223 + case Bytecodes::_ret : 1.224 + case Bytecodes::_ireturn : 1.225 + case Bytecodes::_lreturn : 1.226 + case Bytecodes::_freturn : 1.227 + case Bytecodes::_dreturn : 1.228 + case Bytecodes::_areturn : 1.229 + case Bytecodes::_return : 1.230 + cur_block->set_control_bci(bci); 1.231 + if (s.next_bci() < limit_bci) { 1.232 + (void) make_block_at(s.next_bci()); 1.233 + } 1.234 + break; 1.235 + } 1.236 + } 1.237 + // End the last block 1.238 + cur_block->set_limit_bci(limit_bci); 1.239 +} 1.240 + 1.241 +ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth), 1.242 + _arena(arena), _num_blocks(0), _code_size(meth->code_size()) { 1.243 + int block_estimate = _code_size / 8; 1.244 + 1.245 + _blocks = new(_arena) GrowableArray<ciBlock *>(block_estimate); 1.246 + int b2bsize = _code_size * sizeof(ciBlock **); 1.247 + _bci_to_block = (ciBlock **) arena->Amalloc(b2bsize); 1.248 + Copy::zero_to_words((HeapWord*) _bci_to_block, b2bsize / sizeof(HeapWord)); 1.249 + 1.250 + // create initial block covering the entire method 1.251 + ciBlock *b = new(arena) ciBlock(_method, _num_blocks++, this, 0); 1.252 + _blocks->append(b); 1.253 + _bci_to_block[0] = b; 1.254 + 1.255 + // create blocks for exception handlers 1.256 + if (meth->has_exception_handlers()) { 1.257 + for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { 1.258 + ciExceptionHandler* handler = str.handler(); 1.259 + ciBlock *eb = make_block_at(handler->handler_bci()); 1.260 + eb->set_handler(); 1.261 + int ex_start = handler->start(); 1.262 + int ex_end = handler->limit(); 1.263 + eb->set_exception_range(ex_start, ex_end); 1.264 + // ensure a block at the start of exception range and start of following code 1.265 + (void) make_block_at(ex_start); 1.266 + if (ex_end < _code_size) 1.267 + (void) make_block_at(ex_end); 1.268 + } 1.269 + } 1.270 + 1.271 + // scan the bytecodes and identify blocks 1.272 + do_analysis(); 1.273 + 1.274 + // mark blocks that have exception handlers 1.275 + if (meth->has_exception_handlers()) { 1.276 + for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) { 1.277 + ciExceptionHandler* handler = str.handler(); 1.278 + int ex_start = handler->start(); 1.279 + int ex_end = handler->limit(); 1.280 + 1.281 + int bci = ex_start; 1.282 + while (bci < ex_end) { 1.283 + ciBlock *b = block_containing(bci); 1.284 + b->set_has_handler(); 1.285 + bci = b->limit_bci(); 1.286 + } 1.287 + } 1.288 + } 1.289 +} 1.290 + 1.291 +void ciMethodBlocks::clear_processed() { 1.292 + for (int i = 0; i < _blocks->length(); i++) 1.293 + _blocks->at(i)->clear_processed(); 1.294 +} 1.295 + 1.296 +#ifndef PRODUCT 1.297 +void ciMethodBlocks::dump() { 1.298 + tty->print("---- blocks for method: "); 1.299 + _method->print(); 1.300 + tty->cr(); 1.301 + for (int i = 0; i < _blocks->length(); i++) { 1.302 + tty->print(" B%d: ", i); _blocks->at(i)->dump(); 1.303 + } 1.304 +} 1.305 +#endif 1.306 + 1.307 + 1.308 +ciBlock::ciBlock(ciMethod *method, int index, ciMethodBlocks *mb, int start_bci) : 1.309 +#ifndef PRODUCT 1.310 + _method(method), 1.311 +#endif 1.312 + _idx(index), _flags(0), _start_bci(start_bci), _limit_bci(-1), _control_bci(fall_through_bci), 1.313 + _ex_start_bci(-1), _ex_limit_bci(-1) { 1.314 +} 1.315 + 1.316 +void ciBlock::set_exception_range(int start_bci, int limit_bci) { 1.317 + assert(limit_bci >= start_bci, "valid range"); 1.318 + assert(is_handler(), "must be handler"); 1.319 + _ex_start_bci = start_bci; 1.320 + _ex_limit_bci = limit_bci; 1.321 +} 1.322 + 1.323 +#ifndef PRODUCT 1.324 +static char *flagnames[] = { 1.325 + "Processed", 1.326 + "Handler", 1.327 + "MayThrow", 1.328 + "Jsr", 1.329 + "Ret", 1.330 + "RetTarget", 1.331 + "HasHandler", 1.332 +}; 1.333 + 1.334 +void ciBlock::dump() { 1.335 + tty->print(" [%d .. %d), {", _start_bci, _limit_bci); 1.336 + for (int i = 0; i < 8; i++) { 1.337 + if ((_flags & (1 << i)) != 0) { 1.338 + tty->print(" %s", flagnames[i]); 1.339 + } 1.340 + } 1.341 + tty->print(" ]"); 1.342 + if (is_handler()) 1.343 + tty->print(" handles(%d..%d)", _ex_start_bci, _ex_limit_bci); 1.344 + tty->cr(); 1.345 +} 1.346 + 1.347 +// ------------------------------------------------------------------ 1.348 +// ciBlock::print_on 1.349 +void ciBlock::print_on(outputStream* st) const { 1.350 + st->print_cr("--------------------------------------------------------"); 1.351 + st->print ("ciBlock [%d - %d) control : ", start_bci(), limit_bci()); 1.352 + if (control_bci() == fall_through_bci) { 1.353 + st->print_cr("%d:fall through", limit_bci()); 1.354 + } else { 1.355 + st->print_cr("%d:%s", control_bci(), 1.356 + Bytecodes::name(method()->java_code_at_bci(control_bci()))); 1.357 + } 1.358 + 1.359 + if (Verbose || WizardMode) { 1.360 + method()->print_codes_on(start_bci(), limit_bci(), st); 1.361 + } 1.362 +} 1.363 +#endif