1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/oops/generateOopMap.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,2571 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "interpreter/bytecodeStream.hpp" 1.30 +#include "oops/generateOopMap.hpp" 1.31 +#include "oops/oop.inline.hpp" 1.32 +#include "oops/symbol.hpp" 1.33 +#include "runtime/handles.inline.hpp" 1.34 +#include "runtime/java.hpp" 1.35 +#include "runtime/relocator.hpp" 1.36 +#include "utilities/bitMap.inline.hpp" 1.37 +#include "prims/methodHandles.hpp" 1.38 + 1.39 +// 1.40 +// 1.41 +// Compute stack layouts for each instruction in method. 1.42 +// 1.43 +// Problems: 1.44 +// - What to do about jsr with different types of local vars? 1.45 +// Need maps that are conditional on jsr path? 1.46 +// - Jsr and exceptions should be done more efficiently (the retAddr stuff) 1.47 +// 1.48 +// Alternative: 1.49 +// - Could extend verifier to provide this information. 1.50 +// For: one fewer abstract interpreter to maintain. Against: the verifier 1.51 +// solves a bigger problem so slower (undesirable to force verification of 1.52 +// everything?). 1.53 +// 1.54 +// Algorithm: 1.55 +// Partition bytecodes into basic blocks 1.56 +// For each basic block: store entry state (vars, stack). For instructions 1.57 +// inside basic blocks we do not store any state (instead we recompute it 1.58 +// from state produced by previous instruction). 1.59 +// 1.60 +// Perform abstract interpretation of bytecodes over this lattice: 1.61 +// 1.62 +// _--'#'--_ 1.63 +// / / \ \ 1.64 +// / / \ \ 1.65 +// / | | \ 1.66 +// 'r' 'v' 'p' ' ' 1.67 +// \ | | / 1.68 +// \ \ / / 1.69 +// \ \ / / 1.70 +// -- '@' -- 1.71 +// 1.72 +// '#' top, result of conflict merge 1.73 +// 'r' reference type 1.74 +// 'v' value type 1.75 +// 'p' pc type for jsr/ret 1.76 +// ' ' uninitialized; never occurs on operand stack in Java 1.77 +// '@' bottom/unexecuted; initial state each bytecode. 1.78 +// 1.79 +// Basic block headers are the only merge points. We use this iteration to 1.80 +// compute the information: 1.81 +// 1.82 +// find basic blocks; 1.83 +// initialize them with uninitialized state; 1.84 +// initialize first BB according to method signature; 1.85 +// mark first BB changed 1.86 +// while (some BB is changed) do { 1.87 +// perform abstract interpration of all bytecodes in BB; 1.88 +// merge exit state of BB into entry state of all successor BBs, 1.89 +// noting if any of these change; 1.90 +// } 1.91 +// 1.92 +// One additional complication is necessary. The jsr instruction pushes 1.93 +// a return PC on the stack (a 'p' type in the abstract interpretation). 1.94 +// To be able to process "ret" bytecodes, we keep track of these return 1.95 +// PC's in a 'retAddrs' structure in abstract interpreter context (when 1.96 +// processing a "ret" bytecodes, it is not sufficient to know that it gets 1.97 +// an argument of the right type 'p'; we need to know which address it 1.98 +// returns to). 1.99 +// 1.100 +// (Note this comment is borrowed form the original author of the algorithm) 1.101 + 1.102 +// ComputeCallStack 1.103 +// 1.104 +// Specialization of SignatureIterator - compute the effects of a call 1.105 +// 1.106 +class ComputeCallStack : public SignatureIterator { 1.107 + CellTypeState *_effect; 1.108 + int _idx; 1.109 + 1.110 + void setup(); 1.111 + void set(CellTypeState state) { _effect[_idx++] = state; } 1.112 + int length() { return _idx; }; 1.113 + 1.114 + virtual void do_bool () { set(CellTypeState::value); }; 1.115 + virtual void do_char () { set(CellTypeState::value); }; 1.116 + virtual void do_float () { set(CellTypeState::value); }; 1.117 + virtual void do_byte () { set(CellTypeState::value); }; 1.118 + virtual void do_short () { set(CellTypeState::value); }; 1.119 + virtual void do_int () { set(CellTypeState::value); }; 1.120 + virtual void do_void () { set(CellTypeState::bottom);}; 1.121 + virtual void do_object(int begin, int end) { set(CellTypeState::ref); }; 1.122 + virtual void do_array (int begin, int end) { set(CellTypeState::ref); }; 1.123 + 1.124 + void do_double() { set(CellTypeState::value); 1.125 + set(CellTypeState::value); } 1.126 + void do_long () { set(CellTypeState::value); 1.127 + set(CellTypeState::value); } 1.128 + 1.129 +public: 1.130 + ComputeCallStack(Symbol* signature) : SignatureIterator(signature) {}; 1.131 + 1.132 + // Compute methods 1.133 + int compute_for_parameters(bool is_static, CellTypeState *effect) { 1.134 + _idx = 0; 1.135 + _effect = effect; 1.136 + 1.137 + if (!is_static) 1.138 + effect[_idx++] = CellTypeState::ref; 1.139 + 1.140 + iterate_parameters(); 1.141 + 1.142 + return length(); 1.143 + }; 1.144 + 1.145 + int compute_for_returntype(CellTypeState *effect) { 1.146 + _idx = 0; 1.147 + _effect = effect; 1.148 + iterate_returntype(); 1.149 + set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works 1.150 + 1.151 + return length(); 1.152 + } 1.153 +}; 1.154 + 1.155 +//========================================================================================= 1.156 +// ComputeEntryStack 1.157 +// 1.158 +// Specialization of SignatureIterator - in order to set up first stack frame 1.159 +// 1.160 +class ComputeEntryStack : public SignatureIterator { 1.161 + CellTypeState *_effect; 1.162 + int _idx; 1.163 + 1.164 + void setup(); 1.165 + void set(CellTypeState state) { _effect[_idx++] = state; } 1.166 + int length() { return _idx; }; 1.167 + 1.168 + virtual void do_bool () { set(CellTypeState::value); }; 1.169 + virtual void do_char () { set(CellTypeState::value); }; 1.170 + virtual void do_float () { set(CellTypeState::value); }; 1.171 + virtual void do_byte () { set(CellTypeState::value); }; 1.172 + virtual void do_short () { set(CellTypeState::value); }; 1.173 + virtual void do_int () { set(CellTypeState::value); }; 1.174 + virtual void do_void () { set(CellTypeState::bottom);}; 1.175 + virtual void do_object(int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } 1.176 + virtual void do_array (int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } 1.177 + 1.178 + void do_double() { set(CellTypeState::value); 1.179 + set(CellTypeState::value); } 1.180 + void do_long () { set(CellTypeState::value); 1.181 + set(CellTypeState::value); } 1.182 + 1.183 +public: 1.184 + ComputeEntryStack(Symbol* signature) : SignatureIterator(signature) {}; 1.185 + 1.186 + // Compute methods 1.187 + int compute_for_parameters(bool is_static, CellTypeState *effect) { 1.188 + _idx = 0; 1.189 + _effect = effect; 1.190 + 1.191 + if (!is_static) 1.192 + effect[_idx++] = CellTypeState::make_slot_ref(0); 1.193 + 1.194 + iterate_parameters(); 1.195 + 1.196 + return length(); 1.197 + }; 1.198 + 1.199 + int compute_for_returntype(CellTypeState *effect) { 1.200 + _idx = 0; 1.201 + _effect = effect; 1.202 + iterate_returntype(); 1.203 + set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works 1.204 + 1.205 + return length(); 1.206 + } 1.207 +}; 1.208 + 1.209 +//===================================================================================== 1.210 +// 1.211 +// Implementation of RetTable/RetTableEntry 1.212 +// 1.213 +// Contains function to itereate through all bytecodes 1.214 +// and find all return entry points 1.215 +// 1.216 +int RetTable::_init_nof_entries = 10; 1.217 +int RetTableEntry::_init_nof_jsrs = 5; 1.218 + 1.219 +void RetTableEntry::add_delta(int bci, int delta) { 1.220 + if (_target_bci > bci) _target_bci += delta; 1.221 + 1.222 + for (int k = 0; k < _jsrs->length(); k++) { 1.223 + int jsr = _jsrs->at(k); 1.224 + if (jsr > bci) _jsrs->at_put(k, jsr+delta); 1.225 + } 1.226 +} 1.227 + 1.228 +void RetTable::compute_ret_table(methodHandle method) { 1.229 + BytecodeStream i(method); 1.230 + Bytecodes::Code bytecode; 1.231 + 1.232 + while( (bytecode = i.next()) >= 0) { 1.233 + switch (bytecode) { 1.234 + case Bytecodes::_jsr: 1.235 + add_jsr(i.next_bci(), i.dest()); 1.236 + break; 1.237 + case Bytecodes::_jsr_w: 1.238 + add_jsr(i.next_bci(), i.dest_w()); 1.239 + break; 1.240 + } 1.241 + } 1.242 +} 1.243 + 1.244 +void RetTable::add_jsr(int return_bci, int target_bci) { 1.245 + RetTableEntry* entry = _first; 1.246 + 1.247 + // Scan table for entry 1.248 + for (;entry && entry->target_bci() != target_bci; entry = entry->next()); 1.249 + 1.250 + if (!entry) { 1.251 + // Allocate new entry and put in list 1.252 + entry = new RetTableEntry(target_bci, _first); 1.253 + _first = entry; 1.254 + } 1.255 + 1.256 + // Now "entry" is set. Make sure that the entry is initialized 1.257 + // and has room for the new jsr. 1.258 + entry->add_jsr(return_bci); 1.259 +} 1.260 + 1.261 +RetTableEntry* RetTable::find_jsrs_for_target(int targBci) { 1.262 + RetTableEntry *cur = _first; 1.263 + 1.264 + while(cur) { 1.265 + assert(cur->target_bci() != -1, "sanity check"); 1.266 + if (cur->target_bci() == targBci) return cur; 1.267 + cur = cur->next(); 1.268 + } 1.269 + ShouldNotReachHere(); 1.270 + return NULL; 1.271 +} 1.272 + 1.273 +// The instruction at bci is changing size by "delta". Update the return map. 1.274 +void RetTable::update_ret_table(int bci, int delta) { 1.275 + RetTableEntry *cur = _first; 1.276 + while(cur) { 1.277 + cur->add_delta(bci, delta); 1.278 + cur = cur->next(); 1.279 + } 1.280 +} 1.281 + 1.282 +// 1.283 +// Celltype state 1.284 +// 1.285 + 1.286 +CellTypeState CellTypeState::bottom = CellTypeState::make_bottom(); 1.287 +CellTypeState CellTypeState::uninit = CellTypeState::make_any(uninit_value); 1.288 +CellTypeState CellTypeState::ref = CellTypeState::make_any(ref_conflict); 1.289 +CellTypeState CellTypeState::value = CellTypeState::make_any(val_value); 1.290 +CellTypeState CellTypeState::refUninit = CellTypeState::make_any(ref_conflict | uninit_value); 1.291 +CellTypeState CellTypeState::top = CellTypeState::make_top(); 1.292 +CellTypeState CellTypeState::addr = CellTypeState::make_any(addr_conflict); 1.293 + 1.294 +// Commonly used constants 1.295 +static CellTypeState epsilonCTS[1] = { CellTypeState::bottom }; 1.296 +static CellTypeState refCTS = CellTypeState::ref; 1.297 +static CellTypeState valCTS = CellTypeState::value; 1.298 +static CellTypeState vCTS[2] = { CellTypeState::value, CellTypeState::bottom }; 1.299 +static CellTypeState rCTS[2] = { CellTypeState::ref, CellTypeState::bottom }; 1.300 +static CellTypeState rrCTS[3] = { CellTypeState::ref, CellTypeState::ref, CellTypeState::bottom }; 1.301 +static CellTypeState vrCTS[3] = { CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; 1.302 +static CellTypeState vvCTS[3] = { CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; 1.303 +static CellTypeState rvrCTS[4] = { CellTypeState::ref, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; 1.304 +static CellTypeState vvrCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; 1.305 +static CellTypeState vvvCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; 1.306 +static CellTypeState vvvrCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; 1.307 +static CellTypeState vvvvCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; 1.308 + 1.309 +char CellTypeState::to_char() const { 1.310 + if (can_be_reference()) { 1.311 + if (can_be_value() || can_be_address()) 1.312 + return '#'; // Conflict that needs to be rewritten 1.313 + else 1.314 + return 'r'; 1.315 + } else if (can_be_value()) 1.316 + return 'v'; 1.317 + else if (can_be_address()) 1.318 + return 'p'; 1.319 + else if (can_be_uninit()) 1.320 + return ' '; 1.321 + else 1.322 + return '@'; 1.323 +} 1.324 + 1.325 + 1.326 +// Print a detailed CellTypeState. Indicate all bits that are set. If 1.327 +// the CellTypeState represents an address or a reference, print the 1.328 +// value of the additional information. 1.329 +void CellTypeState::print(outputStream *os) { 1.330 + if (can_be_address()) { 1.331 + os->print("(p"); 1.332 + } else { 1.333 + os->print("( "); 1.334 + } 1.335 + if (can_be_reference()) { 1.336 + os->print("r"); 1.337 + } else { 1.338 + os->print(" "); 1.339 + } 1.340 + if (can_be_value()) { 1.341 + os->print("v"); 1.342 + } else { 1.343 + os->print(" "); 1.344 + } 1.345 + if (can_be_uninit()) { 1.346 + os->print("u|"); 1.347 + } else { 1.348 + os->print(" |"); 1.349 + } 1.350 + if (is_info_top()) { 1.351 + os->print("Top)"); 1.352 + } else if (is_info_bottom()) { 1.353 + os->print("Bot)"); 1.354 + } else { 1.355 + if (is_reference()) { 1.356 + int info = get_info(); 1.357 + int data = info & ~(ref_not_lock_bit | ref_slot_bit); 1.358 + if (info & ref_not_lock_bit) { 1.359 + // Not a monitor lock reference. 1.360 + if (info & ref_slot_bit) { 1.361 + // slot 1.362 + os->print("slot%d)", data); 1.363 + } else { 1.364 + // line 1.365 + os->print("line%d)", data); 1.366 + } 1.367 + } else { 1.368 + // lock 1.369 + os->print("lock%d)", data); 1.370 + } 1.371 + } else { 1.372 + os->print("%d)", get_info()); 1.373 + } 1.374 + } 1.375 +} 1.376 + 1.377 +// 1.378 +// Basicblock handling methods 1.379 +// 1.380 + 1.381 +void GenerateOopMap ::initialize_bb() { 1.382 + _gc_points = 0; 1.383 + _bb_count = 0; 1.384 + _bb_hdr_bits.clear(); 1.385 + _bb_hdr_bits.resize(method()->code_size()); 1.386 +} 1.387 + 1.388 +void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) { 1.389 + assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds"); 1.390 + if (c->is_bb_header(bci)) 1.391 + return; 1.392 + 1.393 + if (TraceNewOopMapGeneration) { 1.394 + tty->print_cr("Basicblock#%d begins at: %d", c->_bb_count, bci); 1.395 + } 1.396 + c->set_bbmark_bit(bci); 1.397 + c->_bb_count++; 1.398 +} 1.399 + 1.400 + 1.401 +void GenerateOopMap::mark_bbheaders_and_count_gc_points() { 1.402 + initialize_bb(); 1.403 + 1.404 + bool fellThrough = false; // False to get first BB marked. 1.405 + 1.406 + // First mark all exception handlers as start of a basic-block 1.407 + ExceptionTable excps(method()); 1.408 + for(int i = 0; i < excps.length(); i ++) { 1.409 + bb_mark_fct(this, excps.handler_pc(i), NULL); 1.410 + } 1.411 + 1.412 + // Then iterate through the code 1.413 + BytecodeStream bcs(_method); 1.414 + Bytecodes::Code bytecode; 1.415 + 1.416 + while( (bytecode = bcs.next()) >= 0) { 1.417 + int bci = bcs.bci(); 1.418 + 1.419 + if (!fellThrough) 1.420 + bb_mark_fct(this, bci, NULL); 1.421 + 1.422 + fellThrough = jump_targets_do(&bcs, &GenerateOopMap::bb_mark_fct, NULL); 1.423 + 1.424 + /* We will also mark successors of jsr's as basic block headers. */ 1.425 + switch (bytecode) { 1.426 + case Bytecodes::_jsr: 1.427 + assert(!fellThrough, "should not happen"); 1.428 + bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL); 1.429 + break; 1.430 + case Bytecodes::_jsr_w: 1.431 + assert(!fellThrough, "should not happen"); 1.432 + bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL); 1.433 + break; 1.434 + } 1.435 + 1.436 + if (possible_gc_point(&bcs)) 1.437 + _gc_points++; 1.438 + } 1.439 +} 1.440 + 1.441 +void GenerateOopMap::reachable_basicblock(GenerateOopMap *c, int bci, int *data) { 1.442 + assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds"); 1.443 + BasicBlock* bb = c->get_basic_block_at(bci); 1.444 + if (bb->is_dead()) { 1.445 + bb->mark_as_alive(); 1.446 + *data = 1; // Mark basicblock as changed 1.447 + } 1.448 +} 1.449 + 1.450 + 1.451 +void GenerateOopMap::mark_reachable_code() { 1.452 + int change = 1; // int to get function pointers to work 1.453 + 1.454 + // Mark entry basic block as alive and all exception handlers 1.455 + _basic_blocks[0].mark_as_alive(); 1.456 + ExceptionTable excps(method()); 1.457 + for(int i = 0; i < excps.length(); i++) { 1.458 + BasicBlock *bb = get_basic_block_at(excps.handler_pc(i)); 1.459 + // If block is not already alive (due to multiple exception handlers to same bb), then 1.460 + // make it alive 1.461 + if (bb->is_dead()) bb->mark_as_alive(); 1.462 + } 1.463 + 1.464 + BytecodeStream bcs(_method); 1.465 + 1.466 + // Iterate through all basic blocks until we reach a fixpoint 1.467 + while (change) { 1.468 + change = 0; 1.469 + 1.470 + for (int i = 0; i < _bb_count; i++) { 1.471 + BasicBlock *bb = &_basic_blocks[i]; 1.472 + if (bb->is_alive()) { 1.473 + // Position bytecodestream at last bytecode in basicblock 1.474 + bcs.set_start(bb->_end_bci); 1.475 + bcs.next(); 1.476 + Bytecodes::Code bytecode = bcs.code(); 1.477 + int bci = bcs.bci(); 1.478 + assert(bci == bb->_end_bci, "wrong bci"); 1.479 + 1.480 + bool fell_through = jump_targets_do(&bcs, &GenerateOopMap::reachable_basicblock, &change); 1.481 + 1.482 + // We will also mark successors of jsr's as alive. 1.483 + switch (bytecode) { 1.484 + case Bytecodes::_jsr: 1.485 + case Bytecodes::_jsr_w: 1.486 + assert(!fell_through, "should not happen"); 1.487 + reachable_basicblock(this, bci + Bytecodes::length_for(bytecode), &change); 1.488 + break; 1.489 + } 1.490 + if (fell_through) { 1.491 + // Mark successor as alive 1.492 + if (bb[1].is_dead()) { 1.493 + bb[1].mark_as_alive(); 1.494 + change = 1; 1.495 + } 1.496 + } 1.497 + } 1.498 + } 1.499 + } 1.500 +} 1.501 + 1.502 +/* If the current instruction in "c" has no effect on control flow, 1.503 + returns "true". Otherwise, calls "jmpFct" one or more times, with 1.504 + "c", an appropriate "pcDelta", and "data" as arguments, then 1.505 + returns "false". There is one exception: if the current 1.506 + instruction is a "ret", returns "false" without calling "jmpFct". 1.507 + Arrangements for tracking the control flow of a "ret" must be made 1.508 + externally. */ 1.509 +bool GenerateOopMap::jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int *data) { 1.510 + int bci = bcs->bci(); 1.511 + 1.512 + switch (bcs->code()) { 1.513 + case Bytecodes::_ifeq: 1.514 + case Bytecodes::_ifne: 1.515 + case Bytecodes::_iflt: 1.516 + case Bytecodes::_ifge: 1.517 + case Bytecodes::_ifgt: 1.518 + case Bytecodes::_ifle: 1.519 + case Bytecodes::_if_icmpeq: 1.520 + case Bytecodes::_if_icmpne: 1.521 + case Bytecodes::_if_icmplt: 1.522 + case Bytecodes::_if_icmpge: 1.523 + case Bytecodes::_if_icmpgt: 1.524 + case Bytecodes::_if_icmple: 1.525 + case Bytecodes::_if_acmpeq: 1.526 + case Bytecodes::_if_acmpne: 1.527 + case Bytecodes::_ifnull: 1.528 + case Bytecodes::_ifnonnull: 1.529 + (*jmpFct)(this, bcs->dest(), data); 1.530 + (*jmpFct)(this, bci + 3, data); 1.531 + break; 1.532 + 1.533 + case Bytecodes::_goto: 1.534 + (*jmpFct)(this, bcs->dest(), data); 1.535 + break; 1.536 + case Bytecodes::_goto_w: 1.537 + (*jmpFct)(this, bcs->dest_w(), data); 1.538 + break; 1.539 + case Bytecodes::_tableswitch: 1.540 + { Bytecode_tableswitch tableswitch(method(), bcs->bcp()); 1.541 + int len = tableswitch.length(); 1.542 + 1.543 + (*jmpFct)(this, bci + tableswitch.default_offset(), data); /* Default. jump address */ 1.544 + while (--len >= 0) { 1.545 + (*jmpFct)(this, bci + tableswitch.dest_offset_at(len), data); 1.546 + } 1.547 + break; 1.548 + } 1.549 + 1.550 + case Bytecodes::_lookupswitch: 1.551 + { Bytecode_lookupswitch lookupswitch(method(), bcs->bcp()); 1.552 + int npairs = lookupswitch.number_of_pairs(); 1.553 + (*jmpFct)(this, bci + lookupswitch.default_offset(), data); /* Default. */ 1.554 + while(--npairs >= 0) { 1.555 + LookupswitchPair pair = lookupswitch.pair_at(npairs); 1.556 + (*jmpFct)(this, bci + pair.offset(), data); 1.557 + } 1.558 + break; 1.559 + } 1.560 + case Bytecodes::_jsr: 1.561 + assert(bcs->is_wide()==false, "sanity check"); 1.562 + (*jmpFct)(this, bcs->dest(), data); 1.563 + 1.564 + 1.565 + 1.566 + break; 1.567 + case Bytecodes::_jsr_w: 1.568 + (*jmpFct)(this, bcs->dest_w(), data); 1.569 + break; 1.570 + case Bytecodes::_wide: 1.571 + ShouldNotReachHere(); 1.572 + return true; 1.573 + break; 1.574 + case Bytecodes::_athrow: 1.575 + case Bytecodes::_ireturn: 1.576 + case Bytecodes::_lreturn: 1.577 + case Bytecodes::_freturn: 1.578 + case Bytecodes::_dreturn: 1.579 + case Bytecodes::_areturn: 1.580 + case Bytecodes::_return: 1.581 + case Bytecodes::_ret: 1.582 + break; 1.583 + default: 1.584 + return true; 1.585 + } 1.586 + return false; 1.587 +} 1.588 + 1.589 +/* Requires "pc" to be the head of a basic block; returns that basic 1.590 + block. */ 1.591 +BasicBlock *GenerateOopMap::get_basic_block_at(int bci) const { 1.592 + BasicBlock* bb = get_basic_block_containing(bci); 1.593 + assert(bb->_bci == bci, "should have found BB"); 1.594 + return bb; 1.595 +} 1.596 + 1.597 +// Requires "pc" to be the start of an instruction; returns the basic 1.598 +// block containing that instruction. */ 1.599 +BasicBlock *GenerateOopMap::get_basic_block_containing(int bci) const { 1.600 + BasicBlock *bbs = _basic_blocks; 1.601 + int lo = 0, hi = _bb_count - 1; 1.602 + 1.603 + while (lo <= hi) { 1.604 + int m = (lo + hi) / 2; 1.605 + int mbci = bbs[m]._bci; 1.606 + int nbci; 1.607 + 1.608 + if ( m == _bb_count-1) { 1.609 + assert( bci >= mbci && bci < method()->code_size(), "sanity check failed"); 1.610 + return bbs+m; 1.611 + } else { 1.612 + nbci = bbs[m+1]._bci; 1.613 + } 1.614 + 1.615 + if ( mbci <= bci && bci < nbci) { 1.616 + return bbs+m; 1.617 + } else if (mbci < bci) { 1.618 + lo = m + 1; 1.619 + } else { 1.620 + assert(mbci > bci, "sanity check"); 1.621 + hi = m - 1; 1.622 + } 1.623 + } 1.624 + 1.625 + fatal("should have found BB"); 1.626 + return NULL; 1.627 +} 1.628 + 1.629 +void GenerateOopMap::restore_state(BasicBlock *bb) 1.630 +{ 1.631 + memcpy(_state, bb->_state, _state_len*sizeof(CellTypeState)); 1.632 + _stack_top = bb->_stack_top; 1.633 + _monitor_top = bb->_monitor_top; 1.634 +} 1.635 + 1.636 +int GenerateOopMap::next_bb_start_pc(BasicBlock *bb) { 1.637 + int bbNum = bb - _basic_blocks + 1; 1.638 + if (bbNum == _bb_count) 1.639 + return method()->code_size(); 1.640 + 1.641 + return _basic_blocks[bbNum]._bci; 1.642 +} 1.643 + 1.644 +// 1.645 +// CellType handling methods 1.646 +// 1.647 + 1.648 +// Allocate memory and throw LinkageError if failure. 1.649 +#define ALLOC_RESOURCE_ARRAY(var, type, count) \ 1.650 + var = NEW_RESOURCE_ARRAY_RETURN_NULL(type, count); \ 1.651 + if (var == NULL) { \ 1.652 + report_error("Cannot reserve enough memory to analyze this method"); \ 1.653 + return; \ 1.654 + } 1.655 + 1.656 + 1.657 +void GenerateOopMap::init_state() { 1.658 + _state_len = _max_locals + _max_stack + _max_monitors; 1.659 + ALLOC_RESOURCE_ARRAY(_state, CellTypeState, _state_len); 1.660 + memset(_state, 0, _state_len * sizeof(CellTypeState)); 1.661 + int count = MAX3(_max_locals, _max_stack, _max_monitors) + 1/*for null terminator char */; 1.662 + ALLOC_RESOURCE_ARRAY(_state_vec_buf, char, count); 1.663 +} 1.664 + 1.665 +void GenerateOopMap::make_context_uninitialized() { 1.666 + CellTypeState* vs = vars(); 1.667 + 1.668 + for (int i = 0; i < _max_locals; i++) 1.669 + vs[i] = CellTypeState::uninit; 1.670 + 1.671 + _stack_top = 0; 1.672 + _monitor_top = 0; 1.673 +} 1.674 + 1.675 +int GenerateOopMap::methodsig_to_effect(Symbol* signature, bool is_static, CellTypeState* effect) { 1.676 + ComputeEntryStack ces(signature); 1.677 + return ces.compute_for_parameters(is_static, effect); 1.678 +} 1.679 + 1.680 +// Return result of merging cts1 and cts2. 1.681 +CellTypeState CellTypeState::merge(CellTypeState cts, int slot) const { 1.682 + CellTypeState result; 1.683 + 1.684 + assert(!is_bottom() && !cts.is_bottom(), 1.685 + "merge of bottom values is handled elsewhere"); 1.686 + 1.687 + result._state = _state | cts._state; 1.688 + 1.689 + // If the top bit is set, we don't need to do any more work. 1.690 + if (!result.is_info_top()) { 1.691 + assert((result.can_be_address() || result.can_be_reference()), 1.692 + "only addresses and references have non-top info"); 1.693 + 1.694 + if (!equal(cts)) { 1.695 + // The two values being merged are different. Raise to top. 1.696 + if (result.is_reference()) { 1.697 + result = CellTypeState::make_slot_ref(slot); 1.698 + } else { 1.699 + result._state |= info_conflict; 1.700 + } 1.701 + } 1.702 + } 1.703 + assert(result.is_valid_state(), "checking that CTS merge maintains legal state"); 1.704 + 1.705 + return result; 1.706 +} 1.707 + 1.708 +// Merge the variable state for locals and stack from cts into bbts. 1.709 +bool GenerateOopMap::merge_local_state_vectors(CellTypeState* cts, 1.710 + CellTypeState* bbts) { 1.711 + int i; 1.712 + int len = _max_locals + _stack_top; 1.713 + bool change = false; 1.714 + 1.715 + for (i = len - 1; i >= 0; i--) { 1.716 + CellTypeState v = cts[i].merge(bbts[i], i); 1.717 + change = change || !v.equal(bbts[i]); 1.718 + bbts[i] = v; 1.719 + } 1.720 + 1.721 + return change; 1.722 +} 1.723 + 1.724 +// Merge the monitor stack state from cts into bbts. 1.725 +bool GenerateOopMap::merge_monitor_state_vectors(CellTypeState* cts, 1.726 + CellTypeState* bbts) { 1.727 + bool change = false; 1.728 + if (_max_monitors > 0 && _monitor_top != bad_monitors) { 1.729 + // If there are no monitors in the program, or there has been 1.730 + // a monitor matching error before this point in the program, 1.731 + // then we do not merge in the monitor state. 1.732 + 1.733 + int base = _max_locals + _max_stack; 1.734 + int len = base + _monitor_top; 1.735 + for (int i = len - 1; i >= base; i--) { 1.736 + CellTypeState v = cts[i].merge(bbts[i], i); 1.737 + 1.738 + // Can we prove that, when there has been a change, it will already 1.739 + // have been detected at this point? That would make this equal 1.740 + // check here unnecessary. 1.741 + change = change || !v.equal(bbts[i]); 1.742 + bbts[i] = v; 1.743 + } 1.744 + } 1.745 + 1.746 + return change; 1.747 +} 1.748 + 1.749 +void GenerateOopMap::copy_state(CellTypeState *dst, CellTypeState *src) { 1.750 + int len = _max_locals + _stack_top; 1.751 + for (int i = 0; i < len; i++) { 1.752 + if (src[i].is_nonlock_reference()) { 1.753 + dst[i] = CellTypeState::make_slot_ref(i); 1.754 + } else { 1.755 + dst[i] = src[i]; 1.756 + } 1.757 + } 1.758 + if (_max_monitors > 0 && _monitor_top != bad_monitors) { 1.759 + int base = _max_locals + _max_stack; 1.760 + len = base + _monitor_top; 1.761 + for (int i = base; i < len; i++) { 1.762 + dst[i] = src[i]; 1.763 + } 1.764 + } 1.765 +} 1.766 + 1.767 + 1.768 +// Merge the states for the current block and the next. As long as a 1.769 +// block is reachable the locals and stack must be merged. If the 1.770 +// stack heights don't match then this is a verification error and 1.771 +// it's impossible to interpret the code. Simultaneously monitor 1.772 +// states are being check to see if they nest statically. If monitor 1.773 +// depths match up then their states are merged. Otherwise the 1.774 +// mismatch is simply recorded and interpretation continues since 1.775 +// monitor matching is purely informational and doesn't say anything 1.776 +// about the correctness of the code. 1.777 +void GenerateOopMap::merge_state_into_bb(BasicBlock *bb) { 1.778 + guarantee(bb != NULL, "null basicblock"); 1.779 + assert(bb->is_alive(), "merging state into a dead basicblock"); 1.780 + 1.781 + if (_stack_top == bb->_stack_top) { 1.782 + // always merge local state even if monitors don't match. 1.783 + if (merge_local_state_vectors(_state, bb->_state)) { 1.784 + bb->set_changed(true); 1.785 + } 1.786 + if (_monitor_top == bb->_monitor_top) { 1.787 + // monitors still match so continue merging monitor states. 1.788 + if (merge_monitor_state_vectors(_state, bb->_state)) { 1.789 + bb->set_changed(true); 1.790 + } 1.791 + } else { 1.792 + if (TraceMonitorMismatch) { 1.793 + report_monitor_mismatch("monitor stack height merge conflict"); 1.794 + } 1.795 + // When the monitor stacks are not matched, we set _monitor_top to 1.796 + // bad_monitors. This signals that, from here on, the monitor stack cannot 1.797 + // be trusted. In particular, monitorexit bytecodes may throw 1.798 + // exceptions. We mark this block as changed so that the change 1.799 + // propagates properly. 1.800 + bb->_monitor_top = bad_monitors; 1.801 + bb->set_changed(true); 1.802 + _monitor_safe = false; 1.803 + } 1.804 + } else if (!bb->is_reachable()) { 1.805 + // First time we look at this BB 1.806 + copy_state(bb->_state, _state); 1.807 + bb->_stack_top = _stack_top; 1.808 + bb->_monitor_top = _monitor_top; 1.809 + bb->set_changed(true); 1.810 + } else { 1.811 + verify_error("stack height conflict: %d vs. %d", _stack_top, bb->_stack_top); 1.812 + } 1.813 +} 1.814 + 1.815 +void GenerateOopMap::merge_state(GenerateOopMap *gom, int bci, int* data) { 1.816 + gom->merge_state_into_bb(gom->get_basic_block_at(bci)); 1.817 +} 1.818 + 1.819 +void GenerateOopMap::set_var(int localNo, CellTypeState cts) { 1.820 + assert(cts.is_reference() || cts.is_value() || cts.is_address(), 1.821 + "wrong celltypestate"); 1.822 + if (localNo < 0 || localNo > _max_locals) { 1.823 + verify_error("variable write error: r%d", localNo); 1.824 + return; 1.825 + } 1.826 + vars()[localNo] = cts; 1.827 +} 1.828 + 1.829 +CellTypeState GenerateOopMap::get_var(int localNo) { 1.830 + assert(localNo < _max_locals + _nof_refval_conflicts, "variable read error"); 1.831 + if (localNo < 0 || localNo > _max_locals) { 1.832 + verify_error("variable read error: r%d", localNo); 1.833 + return valCTS; // just to pick something; 1.834 + } 1.835 + return vars()[localNo]; 1.836 +} 1.837 + 1.838 +CellTypeState GenerateOopMap::pop() { 1.839 + if ( _stack_top <= 0) { 1.840 + verify_error("stack underflow"); 1.841 + return valCTS; // just to pick something 1.842 + } 1.843 + return stack()[--_stack_top]; 1.844 +} 1.845 + 1.846 +void GenerateOopMap::push(CellTypeState cts) { 1.847 + if ( _stack_top >= _max_stack) { 1.848 + verify_error("stack overflow"); 1.849 + return; 1.850 + } 1.851 + stack()[_stack_top++] = cts; 1.852 +} 1.853 + 1.854 +CellTypeState GenerateOopMap::monitor_pop() { 1.855 + assert(_monitor_top != bad_monitors, "monitor_pop called on error monitor stack"); 1.856 + if (_monitor_top == 0) { 1.857 + // We have detected a pop of an empty monitor stack. 1.858 + _monitor_safe = false; 1.859 + _monitor_top = bad_monitors; 1.860 + 1.861 + if (TraceMonitorMismatch) { 1.862 + report_monitor_mismatch("monitor stack underflow"); 1.863 + } 1.864 + return CellTypeState::ref; // just to keep the analysis going. 1.865 + } 1.866 + return monitors()[--_monitor_top]; 1.867 +} 1.868 + 1.869 +void GenerateOopMap::monitor_push(CellTypeState cts) { 1.870 + assert(_monitor_top != bad_monitors, "monitor_push called on error monitor stack"); 1.871 + if (_monitor_top >= _max_monitors) { 1.872 + // Some monitorenter is being executed more than once. 1.873 + // This means that the monitor stack cannot be simulated. 1.874 + _monitor_safe = false; 1.875 + _monitor_top = bad_monitors; 1.876 + 1.877 + if (TraceMonitorMismatch) { 1.878 + report_monitor_mismatch("monitor stack overflow"); 1.879 + } 1.880 + return; 1.881 + } 1.882 + monitors()[_monitor_top++] = cts; 1.883 +} 1.884 + 1.885 +// 1.886 +// Interpretation handling methods 1.887 +// 1.888 + 1.889 +void GenerateOopMap::do_interpretation() 1.890 +{ 1.891 + // "i" is just for debugging, so we can detect cases where this loop is 1.892 + // iterated more than once. 1.893 + int i = 0; 1.894 + do { 1.895 +#ifndef PRODUCT 1.896 + if (TraceNewOopMapGeneration) { 1.897 + tty->print("\n\nIteration #%d of do_interpretation loop, method:\n", i); 1.898 + method()->print_name(tty); 1.899 + tty->print("\n\n"); 1.900 + } 1.901 +#endif 1.902 + _conflict = false; 1.903 + _monitor_safe = true; 1.904 + // init_state is now called from init_basic_blocks. The length of a 1.905 + // state vector cannot be determined until we have made a pass through 1.906 + // the bytecodes counting the possible monitor entries. 1.907 + if (!_got_error) init_basic_blocks(); 1.908 + if (!_got_error) setup_method_entry_state(); 1.909 + if (!_got_error) interp_all(); 1.910 + if (!_got_error) rewrite_refval_conflicts(); 1.911 + i++; 1.912 + } while (_conflict && !_got_error); 1.913 +} 1.914 + 1.915 +void GenerateOopMap::init_basic_blocks() { 1.916 + // Note: Could consider reserving only the needed space for each BB's state 1.917 + // (entry stack may not be of maximal height for every basic block). 1.918 + // But cumbersome since we don't know the stack heights yet. (Nor the 1.919 + // monitor stack heights...) 1.920 + 1.921 + ALLOC_RESOURCE_ARRAY(_basic_blocks, BasicBlock, _bb_count); 1.922 + 1.923 + // Make a pass through the bytecodes. Count the number of monitorenters. 1.924 + // This can be used an upper bound on the monitor stack depth in programs 1.925 + // which obey stack discipline with their monitor usage. Initialize the 1.926 + // known information about basic blocks. 1.927 + BytecodeStream j(_method); 1.928 + Bytecodes::Code bytecode; 1.929 + 1.930 + int bbNo = 0; 1.931 + int monitor_count = 0; 1.932 + int prev_bci = -1; 1.933 + while( (bytecode = j.next()) >= 0) { 1.934 + if (j.code() == Bytecodes::_monitorenter) { 1.935 + monitor_count++; 1.936 + } 1.937 + 1.938 + int bci = j.bci(); 1.939 + if (is_bb_header(bci)) { 1.940 + // Initialize the basicblock structure 1.941 + BasicBlock *bb = _basic_blocks + bbNo; 1.942 + bb->_bci = bci; 1.943 + bb->_max_locals = _max_locals; 1.944 + bb->_max_stack = _max_stack; 1.945 + bb->set_changed(false); 1.946 + bb->_stack_top = BasicBlock::_dead_basic_block; // Initialize all basicblocks are dead. 1.947 + bb->_monitor_top = bad_monitors; 1.948 + 1.949 + if (bbNo > 0) { 1.950 + _basic_blocks[bbNo - 1]._end_bci = prev_bci; 1.951 + } 1.952 + 1.953 + bbNo++; 1.954 + } 1.955 + // Remember prevous bci. 1.956 + prev_bci = bci; 1.957 + } 1.958 + // Set 1.959 + _basic_blocks[bbNo-1]._end_bci = prev_bci; 1.960 + 1.961 + 1.962 + // Check that the correct number of basicblocks was found 1.963 + if (bbNo !=_bb_count) { 1.964 + if (bbNo < _bb_count) { 1.965 + verify_error("jump into the middle of instruction?"); 1.966 + return; 1.967 + } else { 1.968 + verify_error("extra basic blocks - should not happen?"); 1.969 + return; 1.970 + } 1.971 + } 1.972 + 1.973 + _max_monitors = monitor_count; 1.974 + 1.975 + // Now that we have a bound on the depth of the monitor stack, we can 1.976 + // initialize the CellTypeState-related information. 1.977 + init_state(); 1.978 + 1.979 + // We allocate space for all state-vectors for all basicblocks in one huge 1.980 + // chunk. Then in the next part of the code, we set a pointer in each 1.981 + // _basic_block that points to each piece. 1.982 + 1.983 + // The product of bbNo and _state_len can get large if there are lots of 1.984 + // basic blocks and stack/locals/monitors. Need to check to make sure 1.985 + // we don't overflow the capacity of a pointer. 1.986 + if ((unsigned)bbNo > UINTPTR_MAX / sizeof(CellTypeState) / _state_len) { 1.987 + report_error("The amount of memory required to analyze this method " 1.988 + "exceeds addressable range"); 1.989 + return; 1.990 + } 1.991 + 1.992 + CellTypeState *basicBlockState; 1.993 + ALLOC_RESOURCE_ARRAY(basicBlockState, CellTypeState, bbNo * _state_len); 1.994 + memset(basicBlockState, 0, bbNo * _state_len * sizeof(CellTypeState)); 1.995 + 1.996 + // Make a pass over the basicblocks and assign their state vectors. 1.997 + for (int blockNum=0; blockNum < bbNo; blockNum++) { 1.998 + BasicBlock *bb = _basic_blocks + blockNum; 1.999 + bb->_state = basicBlockState + blockNum * _state_len; 1.1000 + 1.1001 +#ifdef ASSERT 1.1002 + if (blockNum + 1 < bbNo) { 1.1003 + address bcp = _method->bcp_from(bb->_end_bci); 1.1004 + int bc_len = Bytecodes::java_length_at(_method(), bcp); 1.1005 + assert(bb->_end_bci + bc_len == bb[1]._bci, "unmatched bci info in basicblock"); 1.1006 + } 1.1007 +#endif 1.1008 + } 1.1009 +#ifdef ASSERT 1.1010 + { BasicBlock *bb = &_basic_blocks[bbNo-1]; 1.1011 + address bcp = _method->bcp_from(bb->_end_bci); 1.1012 + int bc_len = Bytecodes::java_length_at(_method(), bcp); 1.1013 + assert(bb->_end_bci + bc_len == _method->code_size(), "wrong end bci"); 1.1014 + } 1.1015 +#endif 1.1016 + 1.1017 + // Mark all alive blocks 1.1018 + mark_reachable_code(); 1.1019 +} 1.1020 + 1.1021 +void GenerateOopMap::setup_method_entry_state() { 1.1022 + 1.1023 + // Initialize all locals to 'uninit' and set stack-height to 0 1.1024 + make_context_uninitialized(); 1.1025 + 1.1026 + // Initialize CellState type of arguments 1.1027 + methodsig_to_effect(method()->signature(), method()->is_static(), vars()); 1.1028 + 1.1029 + // If some references must be pre-assigned to null, then set that up 1.1030 + initialize_vars(); 1.1031 + 1.1032 + // This is the start state 1.1033 + merge_state_into_bb(&_basic_blocks[0]); 1.1034 + 1.1035 + assert(_basic_blocks[0].changed(), "we are not getting off the ground"); 1.1036 +} 1.1037 + 1.1038 +// The instruction at bci is changing size by "delta". Update the basic blocks. 1.1039 +void GenerateOopMap::update_basic_blocks(int bci, int delta, 1.1040 + int new_method_size) { 1.1041 + assert(new_method_size >= method()->code_size() + delta, 1.1042 + "new method size is too small"); 1.1043 + 1.1044 + BitMap::bm_word_t* new_bb_hdr_bits = 1.1045 + NEW_RESOURCE_ARRAY(BitMap::bm_word_t, 1.1046 + BitMap::word_align_up(new_method_size)); 1.1047 + _bb_hdr_bits.set_map(new_bb_hdr_bits); 1.1048 + _bb_hdr_bits.set_size(new_method_size); 1.1049 + _bb_hdr_bits.clear(); 1.1050 + 1.1051 + 1.1052 + for(int k = 0; k < _bb_count; k++) { 1.1053 + if (_basic_blocks[k]._bci > bci) { 1.1054 + _basic_blocks[k]._bci += delta; 1.1055 + _basic_blocks[k]._end_bci += delta; 1.1056 + } 1.1057 + _bb_hdr_bits.at_put(_basic_blocks[k]._bci, true); 1.1058 + } 1.1059 +} 1.1060 + 1.1061 +// 1.1062 +// Initvars handling 1.1063 +// 1.1064 + 1.1065 +void GenerateOopMap::initialize_vars() { 1.1066 + for (int k = 0; k < _init_vars->length(); k++) 1.1067 + _state[_init_vars->at(k)] = CellTypeState::make_slot_ref(k); 1.1068 +} 1.1069 + 1.1070 +void GenerateOopMap::add_to_ref_init_set(int localNo) { 1.1071 + 1.1072 + if (TraceNewOopMapGeneration) 1.1073 + tty->print_cr("Added init vars: %d", localNo); 1.1074 + 1.1075 + // Is it already in the set? 1.1076 + if (_init_vars->contains(localNo) ) 1.1077 + return; 1.1078 + 1.1079 + _init_vars->append(localNo); 1.1080 +} 1.1081 + 1.1082 +// 1.1083 +// Interpreration code 1.1084 +// 1.1085 + 1.1086 +void GenerateOopMap::interp_all() { 1.1087 + bool change = true; 1.1088 + 1.1089 + while (change && !_got_error) { 1.1090 + change = false; 1.1091 + for (int i = 0; i < _bb_count && !_got_error; i++) { 1.1092 + BasicBlock *bb = &_basic_blocks[i]; 1.1093 + if (bb->changed()) { 1.1094 + if (_got_error) return; 1.1095 + change = true; 1.1096 + bb->set_changed(false); 1.1097 + interp_bb(bb); 1.1098 + } 1.1099 + } 1.1100 + } 1.1101 +} 1.1102 + 1.1103 +void GenerateOopMap::interp_bb(BasicBlock *bb) { 1.1104 + 1.1105 + // We do not want to do anything in case the basic-block has not been initialized. This 1.1106 + // will happen in the case where there is dead-code hang around in a method. 1.1107 + assert(bb->is_reachable(), "should be reachable or deadcode exist"); 1.1108 + restore_state(bb); 1.1109 + 1.1110 + BytecodeStream itr(_method); 1.1111 + 1.1112 + // Set iterator interval to be the current basicblock 1.1113 + int lim_bci = next_bb_start_pc(bb); 1.1114 + itr.set_interval(bb->_bci, lim_bci); 1.1115 + assert(lim_bci != bb->_bci, "must be at least one instruction in a basicblock"); 1.1116 + itr.next(); // read first instruction 1.1117 + 1.1118 + // Iterates through all bytecodes except the last in a basic block. 1.1119 + // We handle the last one special, since there is controlflow change. 1.1120 + while(itr.next_bci() < lim_bci && !_got_error) { 1.1121 + if (_has_exceptions || _monitor_top != 0) { 1.1122 + // We do not need to interpret the results of exceptional 1.1123 + // continuation from this instruction when the method has no 1.1124 + // exception handlers and the monitor stack is currently 1.1125 + // empty. 1.1126 + do_exception_edge(&itr); 1.1127 + } 1.1128 + interp1(&itr); 1.1129 + itr.next(); 1.1130 + } 1.1131 + 1.1132 + // Handle last instruction. 1.1133 + if (!_got_error) { 1.1134 + assert(itr.next_bci() == lim_bci, "must point to end"); 1.1135 + if (_has_exceptions || _monitor_top != 0) { 1.1136 + do_exception_edge(&itr); 1.1137 + } 1.1138 + interp1(&itr); 1.1139 + 1.1140 + bool fall_through = jump_targets_do(&itr, GenerateOopMap::merge_state, NULL); 1.1141 + if (_got_error) return; 1.1142 + 1.1143 + if (itr.code() == Bytecodes::_ret) { 1.1144 + assert(!fall_through, "cannot be set if ret instruction"); 1.1145 + // Automatically handles 'wide' ret indicies 1.1146 + ret_jump_targets_do(&itr, GenerateOopMap::merge_state, itr.get_index(), NULL); 1.1147 + } else if (fall_through) { 1.1148 + // Hit end of BB, but the instr. was a fall-through instruction, 1.1149 + // so perform transition as if the BB ended in a "jump". 1.1150 + if (lim_bci != bb[1]._bci) { 1.1151 + verify_error("bytecodes fell through last instruction"); 1.1152 + return; 1.1153 + } 1.1154 + merge_state_into_bb(bb + 1); 1.1155 + } 1.1156 + } 1.1157 +} 1.1158 + 1.1159 +void GenerateOopMap::do_exception_edge(BytecodeStream* itr) { 1.1160 + // Only check exception edge, if bytecode can trap 1.1161 + if (!Bytecodes::can_trap(itr->code())) return; 1.1162 + switch (itr->code()) { 1.1163 + case Bytecodes::_aload_0: 1.1164 + // These bytecodes can trap for rewriting. We need to assume that 1.1165 + // they do not throw exceptions to make the monitor analysis work. 1.1166 + return; 1.1167 + 1.1168 + case Bytecodes::_ireturn: 1.1169 + case Bytecodes::_lreturn: 1.1170 + case Bytecodes::_freturn: 1.1171 + case Bytecodes::_dreturn: 1.1172 + case Bytecodes::_areturn: 1.1173 + case Bytecodes::_return: 1.1174 + // If the monitor stack height is not zero when we leave the method, 1.1175 + // then we are either exiting with a non-empty stack or we have 1.1176 + // found monitor trouble earlier in our analysis. In either case, 1.1177 + // assume an exception could be taken here. 1.1178 + if (_monitor_top == 0) { 1.1179 + return; 1.1180 + } 1.1181 + break; 1.1182 + 1.1183 + case Bytecodes::_monitorexit: 1.1184 + // If the monitor stack height is bad_monitors, then we have detected a 1.1185 + // monitor matching problem earlier in the analysis. If the 1.1186 + // monitor stack height is 0, we are about to pop a monitor 1.1187 + // off of an empty stack. In either case, the bytecode 1.1188 + // could throw an exception. 1.1189 + if (_monitor_top != bad_monitors && _monitor_top != 0) { 1.1190 + return; 1.1191 + } 1.1192 + break; 1.1193 + } 1.1194 + 1.1195 + if (_has_exceptions) { 1.1196 + int bci = itr->bci(); 1.1197 + ExceptionTable exct(method()); 1.1198 + for(int i = 0; i< exct.length(); i++) { 1.1199 + int start_pc = exct.start_pc(i); 1.1200 + int end_pc = exct.end_pc(i); 1.1201 + int handler_pc = exct.handler_pc(i); 1.1202 + int catch_type = exct.catch_type_index(i); 1.1203 + 1.1204 + if (start_pc <= bci && bci < end_pc) { 1.1205 + BasicBlock *excBB = get_basic_block_at(handler_pc); 1.1206 + guarantee(excBB != NULL, "no basic block for exception"); 1.1207 + CellTypeState *excStk = excBB->stack(); 1.1208 + CellTypeState *cOpStck = stack(); 1.1209 + CellTypeState cOpStck_0 = cOpStck[0]; 1.1210 + int cOpStackTop = _stack_top; 1.1211 + 1.1212 + // Exception stacks are always the same. 1.1213 + assert(method()->max_stack() > 0, "sanity check"); 1.1214 + 1.1215 + // We remembered the size and first element of "cOpStck" 1.1216 + // above; now we temporarily set them to the appropriate 1.1217 + // values for an exception handler. */ 1.1218 + cOpStck[0] = CellTypeState::make_slot_ref(_max_locals); 1.1219 + _stack_top = 1; 1.1220 + 1.1221 + merge_state_into_bb(excBB); 1.1222 + 1.1223 + // Now undo the temporary change. 1.1224 + cOpStck[0] = cOpStck_0; 1.1225 + _stack_top = cOpStackTop; 1.1226 + 1.1227 + // If this is a "catch all" handler, then we do not need to 1.1228 + // consider any additional handlers. 1.1229 + if (catch_type == 0) { 1.1230 + return; 1.1231 + } 1.1232 + } 1.1233 + } 1.1234 + } 1.1235 + 1.1236 + // It is possible that none of the exception handlers would have caught 1.1237 + // the exception. In this case, we will exit the method. We must 1.1238 + // ensure that the monitor stack is empty in this case. 1.1239 + if (_monitor_top == 0) { 1.1240 + return; 1.1241 + } 1.1242 + 1.1243 + // We pessimistically assume that this exception can escape the 1.1244 + // method. (It is possible that it will always be caught, but 1.1245 + // we don't care to analyse the types of the catch clauses.) 1.1246 + 1.1247 + // We don't set _monitor_top to bad_monitors because there are no successors 1.1248 + // to this exceptional exit. 1.1249 + 1.1250 + if (TraceMonitorMismatch && _monitor_safe) { 1.1251 + // We check _monitor_safe so that we only report the first mismatched 1.1252 + // exceptional exit. 1.1253 + report_monitor_mismatch("non-empty monitor stack at exceptional exit"); 1.1254 + } 1.1255 + _monitor_safe = false; 1.1256 + 1.1257 +} 1.1258 + 1.1259 +void GenerateOopMap::report_monitor_mismatch(const char *msg) { 1.1260 +#ifndef PRODUCT 1.1261 + tty->print(" Monitor mismatch in method "); 1.1262 + method()->print_short_name(tty); 1.1263 + tty->print_cr(": %s", msg); 1.1264 +#endif 1.1265 +} 1.1266 + 1.1267 +void GenerateOopMap::print_states(outputStream *os, 1.1268 + CellTypeState* vec, int num) { 1.1269 + for (int i = 0; i < num; i++) { 1.1270 + vec[i].print(tty); 1.1271 + } 1.1272 +} 1.1273 + 1.1274 +// Print the state values at the current bytecode. 1.1275 +void GenerateOopMap::print_current_state(outputStream *os, 1.1276 + BytecodeStream *currentBC, 1.1277 + bool detailed) { 1.1278 + 1.1279 + if (detailed) { 1.1280 + os->print(" %4d vars = ", currentBC->bci()); 1.1281 + print_states(os, vars(), _max_locals); 1.1282 + os->print(" %s", Bytecodes::name(currentBC->code())); 1.1283 + switch(currentBC->code()) { 1.1284 + case Bytecodes::_invokevirtual: 1.1285 + case Bytecodes::_invokespecial: 1.1286 + case Bytecodes::_invokestatic: 1.1287 + case Bytecodes::_invokedynamic: 1.1288 + case Bytecodes::_invokeinterface: 1.1289 + int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2_cpcache(); 1.1290 + ConstantPool* cp = method()->constants(); 1.1291 + int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); 1.1292 + int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); 1.1293 + Symbol* signature = cp->symbol_at(signatureIdx); 1.1294 + os->print("%s", signature->as_C_string()); 1.1295 + } 1.1296 + os->cr(); 1.1297 + os->print(" stack = "); 1.1298 + print_states(os, stack(), _stack_top); 1.1299 + os->cr(); 1.1300 + if (_monitor_top != bad_monitors) { 1.1301 + os->print(" monitors = "); 1.1302 + print_states(os, monitors(), _monitor_top); 1.1303 + } else { 1.1304 + os->print(" [bad monitor stack]"); 1.1305 + } 1.1306 + os->cr(); 1.1307 + } else { 1.1308 + os->print(" %4d vars = '%s' ", currentBC->bci(), state_vec_to_string(vars(), _max_locals)); 1.1309 + os->print(" stack = '%s' ", state_vec_to_string(stack(), _stack_top)); 1.1310 + if (_monitor_top != bad_monitors) { 1.1311 + os->print(" monitors = '%s' \t%s", state_vec_to_string(monitors(), _monitor_top), Bytecodes::name(currentBC->code())); 1.1312 + } else { 1.1313 + os->print(" [bad monitor stack]"); 1.1314 + } 1.1315 + switch(currentBC->code()) { 1.1316 + case Bytecodes::_invokevirtual: 1.1317 + case Bytecodes::_invokespecial: 1.1318 + case Bytecodes::_invokestatic: 1.1319 + case Bytecodes::_invokedynamic: 1.1320 + case Bytecodes::_invokeinterface: 1.1321 + int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2_cpcache(); 1.1322 + ConstantPool* cp = method()->constants(); 1.1323 + int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); 1.1324 + int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); 1.1325 + Symbol* signature = cp->symbol_at(signatureIdx); 1.1326 + os->print("%s", signature->as_C_string()); 1.1327 + } 1.1328 + os->cr(); 1.1329 + } 1.1330 +} 1.1331 + 1.1332 +// Sets the current state to be the state after executing the 1.1333 +// current instruction, starting in the current state. 1.1334 +void GenerateOopMap::interp1(BytecodeStream *itr) { 1.1335 + if (TraceNewOopMapGeneration) { 1.1336 + print_current_state(tty, itr, TraceNewOopMapGenerationDetailed); 1.1337 + } 1.1338 + 1.1339 + // Should we report the results? Result is reported *before* the instruction at the current bci is executed. 1.1340 + // However, not for calls. For calls we do not want to include the arguments, so we postpone the reporting until 1.1341 + // they have been popped (in method ppl). 1.1342 + if (_report_result == true) { 1.1343 + switch(itr->code()) { 1.1344 + case Bytecodes::_invokevirtual: 1.1345 + case Bytecodes::_invokespecial: 1.1346 + case Bytecodes::_invokestatic: 1.1347 + case Bytecodes::_invokedynamic: 1.1348 + case Bytecodes::_invokeinterface: 1.1349 + _itr_send = itr; 1.1350 + _report_result_for_send = true; 1.1351 + break; 1.1352 + default: 1.1353 + fill_stackmap_for_opcodes(itr, vars(), stack(), _stack_top); 1.1354 + break; 1.1355 + } 1.1356 + } 1.1357 + 1.1358 + // abstract interpretation of current opcode 1.1359 + switch(itr->code()) { 1.1360 + case Bytecodes::_nop: break; 1.1361 + case Bytecodes::_goto: break; 1.1362 + case Bytecodes::_goto_w: break; 1.1363 + case Bytecodes::_iinc: break; 1.1364 + case Bytecodes::_return: do_return_monitor_check(); 1.1365 + break; 1.1366 + 1.1367 + case Bytecodes::_aconst_null: 1.1368 + case Bytecodes::_new: ppush1(CellTypeState::make_line_ref(itr->bci())); 1.1369 + break; 1.1370 + 1.1371 + case Bytecodes::_iconst_m1: 1.1372 + case Bytecodes::_iconst_0: 1.1373 + case Bytecodes::_iconst_1: 1.1374 + case Bytecodes::_iconst_2: 1.1375 + case Bytecodes::_iconst_3: 1.1376 + case Bytecodes::_iconst_4: 1.1377 + case Bytecodes::_iconst_5: 1.1378 + case Bytecodes::_fconst_0: 1.1379 + case Bytecodes::_fconst_1: 1.1380 + case Bytecodes::_fconst_2: 1.1381 + case Bytecodes::_bipush: 1.1382 + case Bytecodes::_sipush: ppush1(valCTS); break; 1.1383 + 1.1384 + case Bytecodes::_lconst_0: 1.1385 + case Bytecodes::_lconst_1: 1.1386 + case Bytecodes::_dconst_0: 1.1387 + case Bytecodes::_dconst_1: ppush(vvCTS); break; 1.1388 + 1.1389 + case Bytecodes::_ldc2_w: ppush(vvCTS); break; 1.1390 + 1.1391 + case Bytecodes::_ldc: // fall through: 1.1392 + case Bytecodes::_ldc_w: do_ldc(itr->bci()); break; 1.1393 + 1.1394 + case Bytecodes::_iload: 1.1395 + case Bytecodes::_fload: ppload(vCTS, itr->get_index()); break; 1.1396 + 1.1397 + case Bytecodes::_lload: 1.1398 + case Bytecodes::_dload: ppload(vvCTS,itr->get_index()); break; 1.1399 + 1.1400 + case Bytecodes::_aload: ppload(rCTS, itr->get_index()); break; 1.1401 + 1.1402 + case Bytecodes::_iload_0: 1.1403 + case Bytecodes::_fload_0: ppload(vCTS, 0); break; 1.1404 + case Bytecodes::_iload_1: 1.1405 + case Bytecodes::_fload_1: ppload(vCTS, 1); break; 1.1406 + case Bytecodes::_iload_2: 1.1407 + case Bytecodes::_fload_2: ppload(vCTS, 2); break; 1.1408 + case Bytecodes::_iload_3: 1.1409 + case Bytecodes::_fload_3: ppload(vCTS, 3); break; 1.1410 + 1.1411 + case Bytecodes::_lload_0: 1.1412 + case Bytecodes::_dload_0: ppload(vvCTS, 0); break; 1.1413 + case Bytecodes::_lload_1: 1.1414 + case Bytecodes::_dload_1: ppload(vvCTS, 1); break; 1.1415 + case Bytecodes::_lload_2: 1.1416 + case Bytecodes::_dload_2: ppload(vvCTS, 2); break; 1.1417 + case Bytecodes::_lload_3: 1.1418 + case Bytecodes::_dload_3: ppload(vvCTS, 3); break; 1.1419 + 1.1420 + case Bytecodes::_aload_0: ppload(rCTS, 0); break; 1.1421 + case Bytecodes::_aload_1: ppload(rCTS, 1); break; 1.1422 + case Bytecodes::_aload_2: ppload(rCTS, 2); break; 1.1423 + case Bytecodes::_aload_3: ppload(rCTS, 3); break; 1.1424 + 1.1425 + case Bytecodes::_iaload: 1.1426 + case Bytecodes::_faload: 1.1427 + case Bytecodes::_baload: 1.1428 + case Bytecodes::_caload: 1.1429 + case Bytecodes::_saload: pp(vrCTS, vCTS); break; 1.1430 + 1.1431 + case Bytecodes::_laload: pp(vrCTS, vvCTS); break; 1.1432 + case Bytecodes::_daload: pp(vrCTS, vvCTS); break; 1.1433 + 1.1434 + case Bytecodes::_aaload: pp_new_ref(vrCTS, itr->bci()); break; 1.1435 + 1.1436 + case Bytecodes::_istore: 1.1437 + case Bytecodes::_fstore: ppstore(vCTS, itr->get_index()); break; 1.1438 + 1.1439 + case Bytecodes::_lstore: 1.1440 + case Bytecodes::_dstore: ppstore(vvCTS, itr->get_index()); break; 1.1441 + 1.1442 + case Bytecodes::_astore: do_astore(itr->get_index()); break; 1.1443 + 1.1444 + case Bytecodes::_istore_0: 1.1445 + case Bytecodes::_fstore_0: ppstore(vCTS, 0); break; 1.1446 + case Bytecodes::_istore_1: 1.1447 + case Bytecodes::_fstore_1: ppstore(vCTS, 1); break; 1.1448 + case Bytecodes::_istore_2: 1.1449 + case Bytecodes::_fstore_2: ppstore(vCTS, 2); break; 1.1450 + case Bytecodes::_istore_3: 1.1451 + case Bytecodes::_fstore_3: ppstore(vCTS, 3); break; 1.1452 + 1.1453 + case Bytecodes::_lstore_0: 1.1454 + case Bytecodes::_dstore_0: ppstore(vvCTS, 0); break; 1.1455 + case Bytecodes::_lstore_1: 1.1456 + case Bytecodes::_dstore_1: ppstore(vvCTS, 1); break; 1.1457 + case Bytecodes::_lstore_2: 1.1458 + case Bytecodes::_dstore_2: ppstore(vvCTS, 2); break; 1.1459 + case Bytecodes::_lstore_3: 1.1460 + case Bytecodes::_dstore_3: ppstore(vvCTS, 3); break; 1.1461 + 1.1462 + case Bytecodes::_astore_0: do_astore(0); break; 1.1463 + case Bytecodes::_astore_1: do_astore(1); break; 1.1464 + case Bytecodes::_astore_2: do_astore(2); break; 1.1465 + case Bytecodes::_astore_3: do_astore(3); break; 1.1466 + 1.1467 + case Bytecodes::_iastore: 1.1468 + case Bytecodes::_fastore: 1.1469 + case Bytecodes::_bastore: 1.1470 + case Bytecodes::_castore: 1.1471 + case Bytecodes::_sastore: ppop(vvrCTS); break; 1.1472 + case Bytecodes::_lastore: 1.1473 + case Bytecodes::_dastore: ppop(vvvrCTS); break; 1.1474 + case Bytecodes::_aastore: ppop(rvrCTS); break; 1.1475 + 1.1476 + case Bytecodes::_pop: ppop_any(1); break; 1.1477 + case Bytecodes::_pop2: ppop_any(2); break; 1.1478 + 1.1479 + case Bytecodes::_dup: ppdupswap(1, "11"); break; 1.1480 + case Bytecodes::_dup_x1: ppdupswap(2, "121"); break; 1.1481 + case Bytecodes::_dup_x2: ppdupswap(3, "1321"); break; 1.1482 + case Bytecodes::_dup2: ppdupswap(2, "2121"); break; 1.1483 + case Bytecodes::_dup2_x1: ppdupswap(3, "21321"); break; 1.1484 + case Bytecodes::_dup2_x2: ppdupswap(4, "214321"); break; 1.1485 + case Bytecodes::_swap: ppdupswap(2, "12"); break; 1.1486 + 1.1487 + case Bytecodes::_iadd: 1.1488 + case Bytecodes::_fadd: 1.1489 + case Bytecodes::_isub: 1.1490 + case Bytecodes::_fsub: 1.1491 + case Bytecodes::_imul: 1.1492 + case Bytecodes::_fmul: 1.1493 + case Bytecodes::_idiv: 1.1494 + case Bytecodes::_fdiv: 1.1495 + case Bytecodes::_irem: 1.1496 + case Bytecodes::_frem: 1.1497 + case Bytecodes::_ishl: 1.1498 + case Bytecodes::_ishr: 1.1499 + case Bytecodes::_iushr: 1.1500 + case Bytecodes::_iand: 1.1501 + case Bytecodes::_ior: 1.1502 + case Bytecodes::_ixor: 1.1503 + case Bytecodes::_l2f: 1.1504 + case Bytecodes::_l2i: 1.1505 + case Bytecodes::_d2f: 1.1506 + case Bytecodes::_d2i: 1.1507 + case Bytecodes::_fcmpl: 1.1508 + case Bytecodes::_fcmpg: pp(vvCTS, vCTS); break; 1.1509 + 1.1510 + case Bytecodes::_ladd: 1.1511 + case Bytecodes::_dadd: 1.1512 + case Bytecodes::_lsub: 1.1513 + case Bytecodes::_dsub: 1.1514 + case Bytecodes::_lmul: 1.1515 + case Bytecodes::_dmul: 1.1516 + case Bytecodes::_ldiv: 1.1517 + case Bytecodes::_ddiv: 1.1518 + case Bytecodes::_lrem: 1.1519 + case Bytecodes::_drem: 1.1520 + case Bytecodes::_land: 1.1521 + case Bytecodes::_lor: 1.1522 + case Bytecodes::_lxor: pp(vvvvCTS, vvCTS); break; 1.1523 + 1.1524 + case Bytecodes::_ineg: 1.1525 + case Bytecodes::_fneg: 1.1526 + case Bytecodes::_i2f: 1.1527 + case Bytecodes::_f2i: 1.1528 + case Bytecodes::_i2c: 1.1529 + case Bytecodes::_i2s: 1.1530 + case Bytecodes::_i2b: pp(vCTS, vCTS); break; 1.1531 + 1.1532 + case Bytecodes::_lneg: 1.1533 + case Bytecodes::_dneg: 1.1534 + case Bytecodes::_l2d: 1.1535 + case Bytecodes::_d2l: pp(vvCTS, vvCTS); break; 1.1536 + 1.1537 + case Bytecodes::_lshl: 1.1538 + case Bytecodes::_lshr: 1.1539 + case Bytecodes::_lushr: pp(vvvCTS, vvCTS); break; 1.1540 + 1.1541 + case Bytecodes::_i2l: 1.1542 + case Bytecodes::_i2d: 1.1543 + case Bytecodes::_f2l: 1.1544 + case Bytecodes::_f2d: pp(vCTS, vvCTS); break; 1.1545 + 1.1546 + case Bytecodes::_lcmp: pp(vvvvCTS, vCTS); break; 1.1547 + case Bytecodes::_dcmpl: 1.1548 + case Bytecodes::_dcmpg: pp(vvvvCTS, vCTS); break; 1.1549 + 1.1550 + case Bytecodes::_ifeq: 1.1551 + case Bytecodes::_ifne: 1.1552 + case Bytecodes::_iflt: 1.1553 + case Bytecodes::_ifge: 1.1554 + case Bytecodes::_ifgt: 1.1555 + case Bytecodes::_ifle: 1.1556 + case Bytecodes::_tableswitch: ppop1(valCTS); 1.1557 + break; 1.1558 + case Bytecodes::_ireturn: 1.1559 + case Bytecodes::_freturn: do_return_monitor_check(); 1.1560 + ppop1(valCTS); 1.1561 + break; 1.1562 + case Bytecodes::_if_icmpeq: 1.1563 + case Bytecodes::_if_icmpne: 1.1564 + case Bytecodes::_if_icmplt: 1.1565 + case Bytecodes::_if_icmpge: 1.1566 + case Bytecodes::_if_icmpgt: 1.1567 + case Bytecodes::_if_icmple: ppop(vvCTS); 1.1568 + break; 1.1569 + 1.1570 + case Bytecodes::_lreturn: do_return_monitor_check(); 1.1571 + ppop(vvCTS); 1.1572 + break; 1.1573 + 1.1574 + case Bytecodes::_dreturn: do_return_monitor_check(); 1.1575 + ppop(vvCTS); 1.1576 + break; 1.1577 + 1.1578 + case Bytecodes::_if_acmpeq: 1.1579 + case Bytecodes::_if_acmpne: ppop(rrCTS); break; 1.1580 + 1.1581 + case Bytecodes::_jsr: do_jsr(itr->dest()); break; 1.1582 + case Bytecodes::_jsr_w: do_jsr(itr->dest_w()); break; 1.1583 + 1.1584 + case Bytecodes::_getstatic: do_field(true, true, itr->get_index_u2_cpcache(), itr->bci()); break; 1.1585 + case Bytecodes::_putstatic: do_field(false, true, itr->get_index_u2_cpcache(), itr->bci()); break; 1.1586 + case Bytecodes::_getfield: do_field(true, false, itr->get_index_u2_cpcache(), itr->bci()); break; 1.1587 + case Bytecodes::_putfield: do_field(false, false, itr->get_index_u2_cpcache(), itr->bci()); break; 1.1588 + 1.1589 + case Bytecodes::_invokevirtual: 1.1590 + case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_u2_cpcache(), itr->bci()); break; 1.1591 + case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_u2_cpcache(), itr->bci()); break; 1.1592 + case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_u4(), itr->bci()); break; 1.1593 + case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_u2_cpcache(), itr->bci()); break; 1.1594 + case Bytecodes::_newarray: 1.1595 + case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; 1.1596 + case Bytecodes::_checkcast: do_checkcast(); break; 1.1597 + case Bytecodes::_arraylength: 1.1598 + case Bytecodes::_instanceof: pp(rCTS, vCTS); break; 1.1599 + case Bytecodes::_monitorenter: do_monitorenter(itr->bci()); break; 1.1600 + case Bytecodes::_monitorexit: do_monitorexit(itr->bci()); break; 1.1601 + 1.1602 + case Bytecodes::_athrow: // handled by do_exception_edge() BUT ... 1.1603 + // vlh(apple): do_exception_edge() does not get 1.1604 + // called if method has no exception handlers 1.1605 + if ((!_has_exceptions) && (_monitor_top > 0)) { 1.1606 + _monitor_safe = false; 1.1607 + } 1.1608 + break; 1.1609 + 1.1610 + case Bytecodes::_areturn: do_return_monitor_check(); 1.1611 + ppop1(refCTS); 1.1612 + break; 1.1613 + case Bytecodes::_ifnull: 1.1614 + case Bytecodes::_ifnonnull: ppop1(refCTS); break; 1.1615 + case Bytecodes::_multianewarray: do_multianewarray(*(itr->bcp()+3), itr->bci()); break; 1.1616 + 1.1617 + case Bytecodes::_wide: fatal("Iterator should skip this bytecode"); break; 1.1618 + case Bytecodes::_ret: break; 1.1619 + 1.1620 + // Java opcodes 1.1621 + case Bytecodes::_lookupswitch: ppop1(valCTS); break; 1.1622 + 1.1623 + default: 1.1624 + tty->print("unexpected opcode: %d\n", itr->code()); 1.1625 + ShouldNotReachHere(); 1.1626 + break; 1.1627 + } 1.1628 +} 1.1629 + 1.1630 +void GenerateOopMap::check_type(CellTypeState expected, CellTypeState actual) { 1.1631 + if (!expected.equal_kind(actual)) { 1.1632 + verify_error("wrong type on stack (found: %c expected: %c)", actual.to_char(), expected.to_char()); 1.1633 + } 1.1634 +} 1.1635 + 1.1636 +void GenerateOopMap::ppstore(CellTypeState *in, int loc_no) { 1.1637 + while(!(*in).is_bottom()) { 1.1638 + CellTypeState expected =*in++; 1.1639 + CellTypeState actual = pop(); 1.1640 + check_type(expected, actual); 1.1641 + assert(loc_no >= 0, "sanity check"); 1.1642 + set_var(loc_no++, actual); 1.1643 + } 1.1644 +} 1.1645 + 1.1646 +void GenerateOopMap::ppload(CellTypeState *out, int loc_no) { 1.1647 + while(!(*out).is_bottom()) { 1.1648 + CellTypeState out1 = *out++; 1.1649 + CellTypeState vcts = get_var(loc_no); 1.1650 + assert(out1.can_be_reference() || out1.can_be_value(), 1.1651 + "can only load refs. and values."); 1.1652 + if (out1.is_reference()) { 1.1653 + assert(loc_no>=0, "sanity check"); 1.1654 + if (!vcts.is_reference()) { 1.1655 + // We were asked to push a reference, but the type of the 1.1656 + // variable can be something else 1.1657 + _conflict = true; 1.1658 + if (vcts.can_be_uninit()) { 1.1659 + // It is a ref-uninit conflict (at least). If there are other 1.1660 + // problems, we'll get them in the next round 1.1661 + add_to_ref_init_set(loc_no); 1.1662 + vcts = out1; 1.1663 + } else { 1.1664 + // It wasn't a ref-uninit conflict. So must be a 1.1665 + // ref-val or ref-pc conflict. Split the variable. 1.1666 + record_refval_conflict(loc_no); 1.1667 + vcts = out1; 1.1668 + } 1.1669 + push(out1); // recover... 1.1670 + } else { 1.1671 + push(vcts); // preserve reference. 1.1672 + } 1.1673 + // Otherwise it is a conflict, but one that verification would 1.1674 + // have caught if illegal. In particular, it can't be a topCTS 1.1675 + // resulting from mergeing two difference pcCTS's since the verifier 1.1676 + // would have rejected any use of such a merge. 1.1677 + } else { 1.1678 + push(out1); // handle val/init conflict 1.1679 + } 1.1680 + loc_no++; 1.1681 + } 1.1682 +} 1.1683 + 1.1684 +void GenerateOopMap::ppdupswap(int poplen, const char *out) { 1.1685 + CellTypeState actual[5]; 1.1686 + assert(poplen < 5, "this must be less than length of actual vector"); 1.1687 + 1.1688 + // pop all arguments 1.1689 + for(int i = 0; i < poplen; i++) actual[i] = pop(); 1.1690 + 1.1691 + // put them back 1.1692 + char push_ch = *out++; 1.1693 + while (push_ch != '\0') { 1.1694 + int idx = push_ch - '1'; 1.1695 + assert(idx >= 0 && idx < poplen, "wrong arguments"); 1.1696 + push(actual[idx]); 1.1697 + push_ch = *out++; 1.1698 + } 1.1699 +} 1.1700 + 1.1701 +void GenerateOopMap::ppop1(CellTypeState out) { 1.1702 + CellTypeState actual = pop(); 1.1703 + check_type(out, actual); 1.1704 +} 1.1705 + 1.1706 +void GenerateOopMap::ppop(CellTypeState *out) { 1.1707 + while (!(*out).is_bottom()) { 1.1708 + ppop1(*out++); 1.1709 + } 1.1710 +} 1.1711 + 1.1712 +void GenerateOopMap::ppush1(CellTypeState in) { 1.1713 + assert(in.is_reference() | in.is_value(), "sanity check"); 1.1714 + push(in); 1.1715 +} 1.1716 + 1.1717 +void GenerateOopMap::ppush(CellTypeState *in) { 1.1718 + while (!(*in).is_bottom()) { 1.1719 + ppush1(*in++); 1.1720 + } 1.1721 +} 1.1722 + 1.1723 +void GenerateOopMap::pp(CellTypeState *in, CellTypeState *out) { 1.1724 + ppop(in); 1.1725 + ppush(out); 1.1726 +} 1.1727 + 1.1728 +void GenerateOopMap::pp_new_ref(CellTypeState *in, int bci) { 1.1729 + ppop(in); 1.1730 + ppush1(CellTypeState::make_line_ref(bci)); 1.1731 +} 1.1732 + 1.1733 +void GenerateOopMap::ppop_any(int poplen) { 1.1734 + if (_stack_top >= poplen) { 1.1735 + _stack_top -= poplen; 1.1736 + } else { 1.1737 + verify_error("stack underflow"); 1.1738 + } 1.1739 +} 1.1740 + 1.1741 +// Replace all occurences of the state 'match' with the state 'replace' 1.1742 +// in our current state vector. 1.1743 +void GenerateOopMap::replace_all_CTS_matches(CellTypeState match, 1.1744 + CellTypeState replace) { 1.1745 + int i; 1.1746 + int len = _max_locals + _stack_top; 1.1747 + bool change = false; 1.1748 + 1.1749 + for (i = len - 1; i >= 0; i--) { 1.1750 + if (match.equal(_state[i])) { 1.1751 + _state[i] = replace; 1.1752 + } 1.1753 + } 1.1754 + 1.1755 + if (_monitor_top > 0) { 1.1756 + int base = _max_locals + _max_stack; 1.1757 + len = base + _monitor_top; 1.1758 + for (i = len - 1; i >= base; i--) { 1.1759 + if (match.equal(_state[i])) { 1.1760 + _state[i] = replace; 1.1761 + } 1.1762 + } 1.1763 + } 1.1764 +} 1.1765 + 1.1766 +void GenerateOopMap::do_checkcast() { 1.1767 + CellTypeState actual = pop(); 1.1768 + check_type(refCTS, actual); 1.1769 + push(actual); 1.1770 +} 1.1771 + 1.1772 +void GenerateOopMap::do_monitorenter(int bci) { 1.1773 + CellTypeState actual = pop(); 1.1774 + if (_monitor_top == bad_monitors) { 1.1775 + return; 1.1776 + } 1.1777 + 1.1778 + // Bail out when we get repeated locks on an identical monitor. This case 1.1779 + // isn't too hard to handle and can be made to work if supporting nested 1.1780 + // redundant synchronized statements becomes a priority. 1.1781 + // 1.1782 + // See also "Note" in do_monitorexit(), below. 1.1783 + if (actual.is_lock_reference()) { 1.1784 + _monitor_top = bad_monitors; 1.1785 + _monitor_safe = false; 1.1786 + 1.1787 + if (TraceMonitorMismatch) { 1.1788 + report_monitor_mismatch("nested redundant lock -- bailout..."); 1.1789 + } 1.1790 + return; 1.1791 + } 1.1792 + 1.1793 + CellTypeState lock = CellTypeState::make_lock_ref(bci); 1.1794 + check_type(refCTS, actual); 1.1795 + if (!actual.is_info_top()) { 1.1796 + replace_all_CTS_matches(actual, lock); 1.1797 + monitor_push(lock); 1.1798 + } 1.1799 +} 1.1800 + 1.1801 +void GenerateOopMap::do_monitorexit(int bci) { 1.1802 + CellTypeState actual = pop(); 1.1803 + if (_monitor_top == bad_monitors) { 1.1804 + return; 1.1805 + } 1.1806 + check_type(refCTS, actual); 1.1807 + CellTypeState expected = monitor_pop(); 1.1808 + if (!actual.is_lock_reference() || !expected.equal(actual)) { 1.1809 + // The monitor we are exiting is not verifiably the one 1.1810 + // on the top of our monitor stack. This causes a monitor 1.1811 + // mismatch. 1.1812 + _monitor_top = bad_monitors; 1.1813 + _monitor_safe = false; 1.1814 + 1.1815 + // We need to mark this basic block as changed so that 1.1816 + // this monitorexit will be visited again. We need to 1.1817 + // do this to ensure that we have accounted for the 1.1818 + // possibility that this bytecode will throw an 1.1819 + // exception. 1.1820 + BasicBlock* bb = get_basic_block_containing(bci); 1.1821 + guarantee(bb != NULL, "no basic block for bci"); 1.1822 + bb->set_changed(true); 1.1823 + bb->_monitor_top = bad_monitors; 1.1824 + 1.1825 + if (TraceMonitorMismatch) { 1.1826 + report_monitor_mismatch("improper monitor pair"); 1.1827 + } 1.1828 + } else { 1.1829 + // This code is a fix for the case where we have repeated 1.1830 + // locking of the same object in straightline code. We clear 1.1831 + // out the lock when it is popped from the monitor stack 1.1832 + // and replace it with an unobtrusive reference value that can 1.1833 + // be locked again. 1.1834 + // 1.1835 + // Note: when generateOopMap is fixed to properly handle repeated, 1.1836 + // nested, redundant locks on the same object, then this 1.1837 + // fix will need to be removed at that time. 1.1838 + replace_all_CTS_matches(actual, CellTypeState::make_line_ref(bci)); 1.1839 + } 1.1840 +} 1.1841 + 1.1842 +void GenerateOopMap::do_return_monitor_check() { 1.1843 + if (_monitor_top > 0) { 1.1844 + // The monitor stack must be empty when we leave the method 1.1845 + // for the monitors to be properly matched. 1.1846 + _monitor_safe = false; 1.1847 + 1.1848 + // Since there are no successors to the *return bytecode, it 1.1849 + // isn't necessary to set _monitor_top to bad_monitors. 1.1850 + 1.1851 + if (TraceMonitorMismatch) { 1.1852 + report_monitor_mismatch("non-empty monitor stack at return"); 1.1853 + } 1.1854 + } 1.1855 +} 1.1856 + 1.1857 +void GenerateOopMap::do_jsr(int targ_bci) { 1.1858 + push(CellTypeState::make_addr(targ_bci)); 1.1859 +} 1.1860 + 1.1861 + 1.1862 + 1.1863 +void GenerateOopMap::do_ldc(int bci) { 1.1864 + Bytecode_loadconstant ldc(method(), bci); 1.1865 + ConstantPool* cp = method()->constants(); 1.1866 + constantTag tag = cp->tag_at(ldc.pool_index()); // idx is index in resolved_references 1.1867 + BasicType bt = ldc.result_type(); 1.1868 + CellTypeState cts; 1.1869 + if (tag.basic_type() == T_OBJECT) { 1.1870 + assert(!tag.is_string_index() && !tag.is_klass_index(), "Unexpected index tag"); 1.1871 + assert(bt == T_OBJECT, "Guard is incorrect"); 1.1872 + cts = CellTypeState::make_line_ref(bci); 1.1873 + } else { 1.1874 + assert(bt != T_OBJECT, "Guard is incorrect"); 1.1875 + cts = valCTS; 1.1876 + } 1.1877 + ppush1(cts); 1.1878 +} 1.1879 + 1.1880 +void GenerateOopMap::do_multianewarray(int dims, int bci) { 1.1881 + assert(dims >= 1, "sanity check"); 1.1882 + for(int i = dims -1; i >=0; i--) { 1.1883 + ppop1(valCTS); 1.1884 + } 1.1885 + ppush1(CellTypeState::make_line_ref(bci)); 1.1886 +} 1.1887 + 1.1888 +void GenerateOopMap::do_astore(int idx) { 1.1889 + CellTypeState r_or_p = pop(); 1.1890 + if (!r_or_p.is_address() && !r_or_p.is_reference()) { 1.1891 + // We actually expected ref or pc, but we only report that we expected a ref. It does not 1.1892 + // really matter (at least for now) 1.1893 + verify_error("wrong type on stack (found: %c, expected: {pr})", r_or_p.to_char()); 1.1894 + return; 1.1895 + } 1.1896 + set_var(idx, r_or_p); 1.1897 +} 1.1898 + 1.1899 +// Copies bottom/zero terminated CTS string from "src" into "dst". 1.1900 +// Does NOT terminate with a bottom. Returns the number of cells copied. 1.1901 +int GenerateOopMap::copy_cts(CellTypeState *dst, CellTypeState *src) { 1.1902 + int idx = 0; 1.1903 + while (!src[idx].is_bottom()) { 1.1904 + dst[idx] = src[idx]; 1.1905 + idx++; 1.1906 + } 1.1907 + return idx; 1.1908 +} 1.1909 + 1.1910 +void GenerateOopMap::do_field(int is_get, int is_static, int idx, int bci) { 1.1911 + // Dig up signature for field in constant pool 1.1912 + ConstantPool* cp = method()->constants(); 1.1913 + int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); 1.1914 + int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); 1.1915 + Symbol* signature = cp->symbol_at(signatureIdx); 1.1916 + 1.1917 + // Parse signature (espcially simple for fields) 1.1918 + assert(signature->utf8_length() > 0, "field signatures cannot have zero length"); 1.1919 + // The signature is UFT8 encoded, but the first char is always ASCII for signatures. 1.1920 + char sigch = (char)*(signature->base()); 1.1921 + CellTypeState temp[4]; 1.1922 + CellTypeState *eff = sigchar_to_effect(sigch, bci, temp); 1.1923 + 1.1924 + CellTypeState in[4]; 1.1925 + CellTypeState *out; 1.1926 + int i = 0; 1.1927 + 1.1928 + if (is_get) { 1.1929 + out = eff; 1.1930 + } else { 1.1931 + out = epsilonCTS; 1.1932 + i = copy_cts(in, eff); 1.1933 + } 1.1934 + if (!is_static) in[i++] = CellTypeState::ref; 1.1935 + in[i] = CellTypeState::bottom; 1.1936 + assert(i<=3, "sanity check"); 1.1937 + pp(in, out); 1.1938 +} 1.1939 + 1.1940 +void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) { 1.1941 + // Dig up signature for field in constant pool 1.1942 + ConstantPool* cp = _method->constants(); 1.1943 + Symbol* signature = cp->signature_ref_at(idx); 1.1944 + 1.1945 + // Parse method signature 1.1946 + CellTypeState out[4]; 1.1947 + CellTypeState in[MAXARGSIZE+1]; // Includes result 1.1948 + ComputeCallStack cse(signature); 1.1949 + 1.1950 + // Compute return type 1.1951 + int res_length= cse.compute_for_returntype(out); 1.1952 + 1.1953 + // Temporary hack. 1.1954 + if (out[0].equal(CellTypeState::ref) && out[1].equal(CellTypeState::bottom)) { 1.1955 + out[0] = CellTypeState::make_line_ref(bci); 1.1956 + } 1.1957 + 1.1958 + assert(res_length<=4, "max value should be vv"); 1.1959 + 1.1960 + // Compute arguments 1.1961 + int arg_length = cse.compute_for_parameters(is_static != 0, in); 1.1962 + assert(arg_length<=MAXARGSIZE, "too many locals"); 1.1963 + 1.1964 + // Pop arguments 1.1965 + for (int i = arg_length - 1; i >= 0; i--) ppop1(in[i]);// Do args in reverse order. 1.1966 + 1.1967 + // Report results 1.1968 + if (_report_result_for_send == true) { 1.1969 + fill_stackmap_for_opcodes(_itr_send, vars(), stack(), _stack_top); 1.1970 + _report_result_for_send = false; 1.1971 + } 1.1972 + 1.1973 + // Push return address 1.1974 + ppush(out); 1.1975 +} 1.1976 + 1.1977 +// This is used to parse the signature for fields, since they are very simple... 1.1978 +CellTypeState *GenerateOopMap::sigchar_to_effect(char sigch, int bci, CellTypeState *out) { 1.1979 + // Object and array 1.1980 + if (sigch=='L' || sigch=='[') { 1.1981 + out[0] = CellTypeState::make_line_ref(bci); 1.1982 + out[1] = CellTypeState::bottom; 1.1983 + return out; 1.1984 + } 1.1985 + if (sigch == 'J' || sigch == 'D' ) return vvCTS; // Long and Double 1.1986 + if (sigch == 'V' ) return epsilonCTS; // Void 1.1987 + return vCTS; // Otherwise 1.1988 +} 1.1989 + 1.1990 +long GenerateOopMap::_total_byte_count = 0; 1.1991 +elapsedTimer GenerateOopMap::_total_oopmap_time; 1.1992 + 1.1993 +// This function assumes "bcs" is at a "ret" instruction and that the vars 1.1994 +// state is valid for that instruction. Furthermore, the ret instruction 1.1995 +// must be the last instruction in "bb" (we store information about the 1.1996 +// "ret" in "bb"). 1.1997 +void GenerateOopMap::ret_jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int varNo, int *data) { 1.1998 + CellTypeState ra = vars()[varNo]; 1.1999 + if (!ra.is_good_address()) { 1.2000 + verify_error("ret returns from two jsr subroutines?"); 1.2001 + return; 1.2002 + } 1.2003 + int target = ra.get_info(); 1.2004 + 1.2005 + RetTableEntry* rtEnt = _rt.find_jsrs_for_target(target); 1.2006 + int bci = bcs->bci(); 1.2007 + for (int i = 0; i < rtEnt->nof_jsrs(); i++) { 1.2008 + int target_bci = rtEnt->jsrs(i); 1.2009 + // Make sure a jrtRet does not set the changed bit for dead basicblock. 1.2010 + BasicBlock* jsr_bb = get_basic_block_containing(target_bci - 1); 1.2011 + debug_only(BasicBlock* target_bb = &jsr_bb[1];) 1.2012 + assert(target_bb == get_basic_block_at(target_bci), "wrong calc. of successor basicblock"); 1.2013 + bool alive = jsr_bb->is_alive(); 1.2014 + if (TraceNewOopMapGeneration) { 1.2015 + tty->print("pc = %d, ret -> %d alive: %s\n", bci, target_bci, alive ? "true" : "false"); 1.2016 + } 1.2017 + if (alive) jmpFct(this, target_bci, data); 1.2018 + } 1.2019 +} 1.2020 + 1.2021 +// 1.2022 +// Debug method 1.2023 +// 1.2024 +char* GenerateOopMap::state_vec_to_string(CellTypeState* vec, int len) { 1.2025 +#ifdef ASSERT 1.2026 + int checklen = MAX3(_max_locals, _max_stack, _max_monitors) + 1; 1.2027 + assert(len < checklen, "state_vec_buf overflow"); 1.2028 +#endif 1.2029 + for (int i = 0; i < len; i++) _state_vec_buf[i] = vec[i].to_char(); 1.2030 + _state_vec_buf[len] = 0; 1.2031 + return _state_vec_buf; 1.2032 +} 1.2033 + 1.2034 +void GenerateOopMap::print_time() { 1.2035 + tty->print_cr ("Accumulated oopmap times:"); 1.2036 + tty->print_cr ("---------------------------"); 1.2037 + tty->print_cr (" Total : %3.3f sec.", GenerateOopMap::_total_oopmap_time.seconds()); 1.2038 + tty->print_cr (" (%3.0f bytecodes per sec) ", 1.2039 + GenerateOopMap::_total_byte_count / GenerateOopMap::_total_oopmap_time.seconds()); 1.2040 +} 1.2041 + 1.2042 +// 1.2043 +// ============ Main Entry Point =========== 1.2044 +// 1.2045 +GenerateOopMap::GenerateOopMap(methodHandle method) { 1.2046 + // We have to initialize all variables here, that can be queried directly 1.2047 + _method = method; 1.2048 + _max_locals=0; 1.2049 + _init_vars = NULL; 1.2050 + 1.2051 +#ifndef PRODUCT 1.2052 + // If we are doing a detailed trace, include the regular trace information. 1.2053 + if (TraceNewOopMapGenerationDetailed) { 1.2054 + TraceNewOopMapGeneration = true; 1.2055 + } 1.2056 +#endif 1.2057 +} 1.2058 + 1.2059 +void GenerateOopMap::compute_map(TRAPS) { 1.2060 +#ifndef PRODUCT 1.2061 + if (TimeOopMap2) { 1.2062 + method()->print_short_name(tty); 1.2063 + tty->print(" "); 1.2064 + } 1.2065 + if (TimeOopMap) { 1.2066 + _total_byte_count += method()->code_size(); 1.2067 + } 1.2068 +#endif 1.2069 + TraceTime t_single("oopmap time", TimeOopMap2); 1.2070 + TraceTime t_all(NULL, &_total_oopmap_time, TimeOopMap); 1.2071 + 1.2072 + // Initialize values 1.2073 + _got_error = false; 1.2074 + _conflict = false; 1.2075 + _max_locals = method()->max_locals(); 1.2076 + _max_stack = method()->max_stack(); 1.2077 + _has_exceptions = (method()->has_exception_handler()); 1.2078 + _nof_refval_conflicts = 0; 1.2079 + _init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars 1.2080 + _report_result = false; 1.2081 + _report_result_for_send = false; 1.2082 + _new_var_map = NULL; 1.2083 + _ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number; 1.2084 + _did_rewriting = false; 1.2085 + _did_relocation = false; 1.2086 + 1.2087 + if (TraceNewOopMapGeneration) { 1.2088 + tty->print("Method name: %s\n", method()->name()->as_C_string()); 1.2089 + if (Verbose) { 1.2090 + _method->print_codes(); 1.2091 + tty->print_cr("Exception table:"); 1.2092 + ExceptionTable excps(method()); 1.2093 + for(int i = 0; i < excps.length(); i ++) { 1.2094 + tty->print_cr("[%d - %d] -> %d", 1.2095 + excps.start_pc(i), excps.end_pc(i), excps.handler_pc(i)); 1.2096 + } 1.2097 + } 1.2098 + } 1.2099 + 1.2100 + // if no code - do nothing 1.2101 + // compiler needs info 1.2102 + if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) { 1.2103 + fill_stackmap_prolog(0); 1.2104 + fill_stackmap_epilog(); 1.2105 + return; 1.2106 + } 1.2107 + // Step 1: Compute all jump targets and their return value 1.2108 + if (!_got_error) 1.2109 + _rt.compute_ret_table(_method); 1.2110 + 1.2111 + // Step 2: Find all basic blocks and count GC points 1.2112 + if (!_got_error) 1.2113 + mark_bbheaders_and_count_gc_points(); 1.2114 + 1.2115 + // Step 3: Calculate stack maps 1.2116 + if (!_got_error) 1.2117 + do_interpretation(); 1.2118 + 1.2119 + // Step 4:Return results 1.2120 + if (!_got_error && report_results()) 1.2121 + report_result(); 1.2122 + 1.2123 + if (_got_error) { 1.2124 + THROW_HANDLE(_exception); 1.2125 + } 1.2126 +} 1.2127 + 1.2128 +// Error handling methods 1.2129 +// These methods create an exception for the current thread which is thrown 1.2130 +// at the bottom of the call stack, when it returns to compute_map(). The 1.2131 +// _got_error flag controls execution. NOT TODO: The VM exception propagation 1.2132 +// mechanism using TRAPS/CHECKs could be used here instead but it would need 1.2133 +// to be added as a parameter to every function and checked for every call. 1.2134 +// The tons of extra code it would generate didn't seem worth the change. 1.2135 +// 1.2136 +void GenerateOopMap::error_work(const char *format, va_list ap) { 1.2137 + _got_error = true; 1.2138 + char msg_buffer[512]; 1.2139 + vsnprintf(msg_buffer, sizeof(msg_buffer), format, ap); 1.2140 + // Append method name 1.2141 + char msg_buffer2[512]; 1.2142 + jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string()); 1.2143 + _exception = Exceptions::new_exception(Thread::current(), 1.2144 + vmSymbols::java_lang_LinkageError(), msg_buffer2); 1.2145 +} 1.2146 + 1.2147 +void GenerateOopMap::report_error(const char *format, ...) { 1.2148 + va_list ap; 1.2149 + va_start(ap, format); 1.2150 + error_work(format, ap); 1.2151 +} 1.2152 + 1.2153 +void GenerateOopMap::verify_error(const char *format, ...) { 1.2154 + // We do not distinguish between different types of errors for verification 1.2155 + // errors. Let the verifier give a better message. 1.2156 + const char *msg = "Illegal class file encountered. Try running with -Xverify:all"; 1.2157 + _got_error = true; 1.2158 + // Append method name 1.2159 + char msg_buffer2[512]; 1.2160 + jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg, 1.2161 + method()->name()->as_C_string()); 1.2162 + _exception = Exceptions::new_exception(Thread::current(), 1.2163 + vmSymbols::java_lang_LinkageError(), msg_buffer2); 1.2164 +} 1.2165 + 1.2166 +// 1.2167 +// Report result opcodes 1.2168 +// 1.2169 +void GenerateOopMap::report_result() { 1.2170 + 1.2171 + if (TraceNewOopMapGeneration) tty->print_cr("Report result pass"); 1.2172 + 1.2173 + // We now want to report the result of the parse 1.2174 + _report_result = true; 1.2175 + 1.2176 + // Prolog code 1.2177 + fill_stackmap_prolog(_gc_points); 1.2178 + 1.2179 + // Mark everything changed, then do one interpretation pass. 1.2180 + for (int i = 0; i<_bb_count; i++) { 1.2181 + if (_basic_blocks[i].is_reachable()) { 1.2182 + _basic_blocks[i].set_changed(true); 1.2183 + interp_bb(&_basic_blocks[i]); 1.2184 + } 1.2185 + } 1.2186 + 1.2187 + // Note: Since we are skipping dead-code when we are reporting results, then 1.2188 + // the no. of encountered gc-points might be fewer than the previously number 1.2189 + // we have counted. (dead-code is a pain - it should be removed before we get here) 1.2190 + fill_stackmap_epilog(); 1.2191 + 1.2192 + // Report initvars 1.2193 + fill_init_vars(_init_vars); 1.2194 + 1.2195 + _report_result = false; 1.2196 +} 1.2197 + 1.2198 +void GenerateOopMap::result_for_basicblock(int bci) { 1.2199 + if (TraceNewOopMapGeneration) tty->print_cr("Report result pass for basicblock"); 1.2200 + 1.2201 + // We now want to report the result of the parse 1.2202 + _report_result = true; 1.2203 + 1.2204 + // Find basicblock and report results 1.2205 + BasicBlock* bb = get_basic_block_containing(bci); 1.2206 + guarantee(bb != NULL, "no basic block for bci"); 1.2207 + assert(bb->is_reachable(), "getting result from unreachable basicblock"); 1.2208 + bb->set_changed(true); 1.2209 + interp_bb(bb); 1.2210 +} 1.2211 + 1.2212 +// 1.2213 +// Conflict handling code 1.2214 +// 1.2215 + 1.2216 +void GenerateOopMap::record_refval_conflict(int varNo) { 1.2217 + assert(varNo>=0 && varNo< _max_locals, "index out of range"); 1.2218 + 1.2219 + if (TraceOopMapRewrites) { 1.2220 + tty->print("### Conflict detected (local no: %d)\n", varNo); 1.2221 + } 1.2222 + 1.2223 + if (!_new_var_map) { 1.2224 + _new_var_map = NEW_RESOURCE_ARRAY(int, _max_locals); 1.2225 + for (int k = 0; k < _max_locals; k++) _new_var_map[k] = k; 1.2226 + } 1.2227 + 1.2228 + if ( _new_var_map[varNo] == varNo) { 1.2229 + // Check if max. number of locals has been reached 1.2230 + if (_max_locals + _nof_refval_conflicts >= MAX_LOCAL_VARS) { 1.2231 + report_error("Rewriting exceeded local variable limit"); 1.2232 + return; 1.2233 + } 1.2234 + _new_var_map[varNo] = _max_locals + _nof_refval_conflicts; 1.2235 + _nof_refval_conflicts++; 1.2236 + } 1.2237 +} 1.2238 + 1.2239 +void GenerateOopMap::rewrite_refval_conflicts() 1.2240 +{ 1.2241 + // We can get here two ways: Either a rewrite conflict was detected, or 1.2242 + // an uninitialize reference was detected. In the second case, we do not 1.2243 + // do any rewriting, we just want to recompute the reference set with the 1.2244 + // new information 1.2245 + 1.2246 + int nof_conflicts = 0; // Used for debugging only 1.2247 + 1.2248 + if ( _nof_refval_conflicts == 0 ) 1.2249 + return; 1.2250 + 1.2251 + // Check if rewrites are allowed in this parse. 1.2252 + if (!allow_rewrites() && !IgnoreRewrites) { 1.2253 + fatal("Rewriting method not allowed at this stage"); 1.2254 + } 1.2255 + 1.2256 + 1.2257 + // This following flag is to tempoary supress rewrites. The locals that might conflict will 1.2258 + // all be set to contain values. This is UNSAFE - however, until the rewriting has been completely 1.2259 + // tested it is nice to have. 1.2260 + if (IgnoreRewrites) { 1.2261 + if (Verbose) { 1.2262 + tty->print("rewrites suppressed for local no. "); 1.2263 + for (int l = 0; l < _max_locals; l++) { 1.2264 + if (_new_var_map[l] != l) { 1.2265 + tty->print("%d ", l); 1.2266 + vars()[l] = CellTypeState::value; 1.2267 + } 1.2268 + } 1.2269 + tty->cr(); 1.2270 + } 1.2271 + 1.2272 + // That was that... 1.2273 + _new_var_map = NULL; 1.2274 + _nof_refval_conflicts = 0; 1.2275 + _conflict = false; 1.2276 + 1.2277 + return; 1.2278 + } 1.2279 + 1.2280 + // Tracing flag 1.2281 + _did_rewriting = true; 1.2282 + 1.2283 + if (TraceOopMapRewrites) { 1.2284 + tty->print_cr("ref/value conflict for method %s - bytecodes are getting rewritten", method()->name()->as_C_string()); 1.2285 + method()->print(); 1.2286 + method()->print_codes(); 1.2287 + } 1.2288 + 1.2289 + assert(_new_var_map!=NULL, "nothing to rewrite"); 1.2290 + assert(_conflict==true, "We should not be here"); 1.2291 + 1.2292 + compute_ret_adr_at_TOS(); 1.2293 + if (!_got_error) { 1.2294 + for (int k = 0; k < _max_locals && !_got_error; k++) { 1.2295 + if (_new_var_map[k] != k) { 1.2296 + if (TraceOopMapRewrites) { 1.2297 + tty->print_cr("Rewriting: %d -> %d", k, _new_var_map[k]); 1.2298 + } 1.2299 + rewrite_refval_conflict(k, _new_var_map[k]); 1.2300 + if (_got_error) return; 1.2301 + nof_conflicts++; 1.2302 + } 1.2303 + } 1.2304 + } 1.2305 + 1.2306 + assert(nof_conflicts == _nof_refval_conflicts, "sanity check"); 1.2307 + 1.2308 + // Adjust the number of locals 1.2309 + method()->set_max_locals(_max_locals+_nof_refval_conflicts); 1.2310 + _max_locals += _nof_refval_conflicts; 1.2311 + 1.2312 + // That was that... 1.2313 + _new_var_map = NULL; 1.2314 + _nof_refval_conflicts = 0; 1.2315 +} 1.2316 + 1.2317 +void GenerateOopMap::rewrite_refval_conflict(int from, int to) { 1.2318 + bool startOver; 1.2319 + do { 1.2320 + // Make sure that the BytecodeStream is constructed in the loop, since 1.2321 + // during rewriting a new method oop is going to be used, and the next time 1.2322 + // around we want to use that. 1.2323 + BytecodeStream bcs(_method); 1.2324 + startOver = false; 1.2325 + 1.2326 + while( !startOver && !_got_error && 1.2327 + // test bcs in case method changed and it became invalid 1.2328 + bcs.next() >=0) { 1.2329 + startOver = rewrite_refval_conflict_inst(&bcs, from, to); 1.2330 + } 1.2331 + } while (startOver && !_got_error); 1.2332 +} 1.2333 + 1.2334 +/* If the current instruction is one that uses local variable "from" 1.2335 + in a ref way, change it to use "to". There's a subtle reason why we 1.2336 + renumber the ref uses and not the non-ref uses: non-ref uses may be 1.2337 + 2 slots wide (double, long) which would necessitate keeping track of 1.2338 + whether we should add one or two variables to the method. If the change 1.2339 + affected the width of some instruction, returns "TRUE"; otherwise, returns "FALSE". 1.2340 + Another reason for moving ref's value is for solving (addr, ref) conflicts, which 1.2341 + both uses aload/astore methods. 1.2342 +*/ 1.2343 +bool GenerateOopMap::rewrite_refval_conflict_inst(BytecodeStream *itr, int from, int to) { 1.2344 + Bytecodes::Code bc = itr->code(); 1.2345 + int index; 1.2346 + int bci = itr->bci(); 1.2347 + 1.2348 + if (is_aload(itr, &index) && index == from) { 1.2349 + if (TraceOopMapRewrites) { 1.2350 + tty->print_cr("Rewriting aload at bci: %d", bci); 1.2351 + } 1.2352 + return rewrite_load_or_store(itr, Bytecodes::_aload, Bytecodes::_aload_0, to); 1.2353 + } 1.2354 + 1.2355 + if (is_astore(itr, &index) && index == from) { 1.2356 + if (!stack_top_holds_ret_addr(bci)) { 1.2357 + if (TraceOopMapRewrites) { 1.2358 + tty->print_cr("Rewriting astore at bci: %d", bci); 1.2359 + } 1.2360 + return rewrite_load_or_store(itr, Bytecodes::_astore, Bytecodes::_astore_0, to); 1.2361 + } else { 1.2362 + if (TraceOopMapRewrites) { 1.2363 + tty->print_cr("Supress rewriting of astore at bci: %d", bci); 1.2364 + } 1.2365 + } 1.2366 + } 1.2367 + 1.2368 + return false; 1.2369 +} 1.2370 + 1.2371 +// The argument to this method is: 1.2372 +// bc : Current bytecode 1.2373 +// bcN : either _aload or _astore 1.2374 +// bc0 : either _aload_0 or _astore_0 1.2375 +bool GenerateOopMap::rewrite_load_or_store(BytecodeStream *bcs, Bytecodes::Code bcN, Bytecodes::Code bc0, unsigned int varNo) { 1.2376 + assert(bcN == Bytecodes::_astore || bcN == Bytecodes::_aload, "wrong argument (bcN)"); 1.2377 + assert(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0, "wrong argument (bc0)"); 1.2378 + int ilen = Bytecodes::length_at(_method(), bcs->bcp()); 1.2379 + int newIlen; 1.2380 + 1.2381 + if (ilen == 4) { 1.2382 + // Original instruction was wide; keep it wide for simplicity 1.2383 + newIlen = 4; 1.2384 + } else if (varNo < 4) 1.2385 + newIlen = 1; 1.2386 + else if (varNo >= 256) 1.2387 + newIlen = 4; 1.2388 + else 1.2389 + newIlen = 2; 1.2390 + 1.2391 + // If we need to relocate in order to patch the byte, we 1.2392 + // do the patching in a temp. buffer, that is passed to the reloc. 1.2393 + // The patching of the bytecode stream is then done by the Relocator. 1.2394 + // This is neccesary, since relocating the instruction at a certain bci, might 1.2395 + // also relocate that instruction, e.g., if a _goto before it gets widen to a _goto_w. 1.2396 + // Hence, we do not know which bci to patch after relocation. 1.2397 + 1.2398 + assert(newIlen <= 4, "sanity check"); 1.2399 + u_char inst_buffer[4]; // Max. instruction size is 4. 1.2400 + address bcp; 1.2401 + 1.2402 + if (newIlen != ilen) { 1.2403 + // Relocation needed do patching in temp. buffer 1.2404 + bcp = (address)inst_buffer; 1.2405 + } else { 1.2406 + bcp = _method->bcp_from(bcs->bci()); 1.2407 + } 1.2408 + 1.2409 + // Patch either directly in Method* or in temp. buffer 1.2410 + if (newIlen == 1) { 1.2411 + assert(varNo < 4, "varNo too large"); 1.2412 + *bcp = bc0 + varNo; 1.2413 + } else if (newIlen == 2) { 1.2414 + assert(varNo < 256, "2-byte index needed!"); 1.2415 + *(bcp + 0) = bcN; 1.2416 + *(bcp + 1) = varNo; 1.2417 + } else { 1.2418 + assert(newIlen == 4, "Wrong instruction length"); 1.2419 + *(bcp + 0) = Bytecodes::_wide; 1.2420 + *(bcp + 1) = bcN; 1.2421 + Bytes::put_Java_u2(bcp+2, varNo); 1.2422 + } 1.2423 + 1.2424 + if (newIlen != ilen) { 1.2425 + expand_current_instr(bcs->bci(), ilen, newIlen, inst_buffer); 1.2426 + } 1.2427 + 1.2428 + 1.2429 + return (newIlen != ilen); 1.2430 +} 1.2431 + 1.2432 +class RelocCallback : public RelocatorListener { 1.2433 + private: 1.2434 + GenerateOopMap* _gom; 1.2435 + public: 1.2436 + RelocCallback(GenerateOopMap* gom) { _gom = gom; }; 1.2437 + 1.2438 + // Callback method 1.2439 + virtual void relocated(int bci, int delta, int new_code_length) { 1.2440 + _gom->update_basic_blocks (bci, delta, new_code_length); 1.2441 + _gom->update_ret_adr_at_TOS(bci, delta); 1.2442 + _gom->_rt.update_ret_table (bci, delta); 1.2443 + } 1.2444 +}; 1.2445 + 1.2446 +// Returns true if expanding was succesful. Otherwise, reports an error and 1.2447 +// returns false. 1.2448 +void GenerateOopMap::expand_current_instr(int bci, int ilen, int newIlen, u_char inst_buffer[]) { 1.2449 + Thread *THREAD = Thread::current(); // Could really have TRAPS argument. 1.2450 + RelocCallback rcb(this); 1.2451 + Relocator rc(_method, &rcb); 1.2452 + methodHandle m= rc.insert_space_at(bci, newIlen, inst_buffer, THREAD); 1.2453 + if (m.is_null() || HAS_PENDING_EXCEPTION) { 1.2454 + report_error("could not rewrite method - exception occurred or bytecode buffer overflow"); 1.2455 + return; 1.2456 + } 1.2457 + 1.2458 + // Relocator returns a new method oop. 1.2459 + _did_relocation = true; 1.2460 + _method = m; 1.2461 +} 1.2462 + 1.2463 + 1.2464 +bool GenerateOopMap::is_astore(BytecodeStream *itr, int *index) { 1.2465 + Bytecodes::Code bc = itr->code(); 1.2466 + switch(bc) { 1.2467 + case Bytecodes::_astore_0: 1.2468 + case Bytecodes::_astore_1: 1.2469 + case Bytecodes::_astore_2: 1.2470 + case Bytecodes::_astore_3: 1.2471 + *index = bc - Bytecodes::_astore_0; 1.2472 + return true; 1.2473 + case Bytecodes::_astore: 1.2474 + *index = itr->get_index(); 1.2475 + return true; 1.2476 + } 1.2477 + return false; 1.2478 +} 1.2479 + 1.2480 +bool GenerateOopMap::is_aload(BytecodeStream *itr, int *index) { 1.2481 + Bytecodes::Code bc = itr->code(); 1.2482 + switch(bc) { 1.2483 + case Bytecodes::_aload_0: 1.2484 + case Bytecodes::_aload_1: 1.2485 + case Bytecodes::_aload_2: 1.2486 + case Bytecodes::_aload_3: 1.2487 + *index = bc - Bytecodes::_aload_0; 1.2488 + return true; 1.2489 + 1.2490 + case Bytecodes::_aload: 1.2491 + *index = itr->get_index(); 1.2492 + return true; 1.2493 + } 1.2494 + return false; 1.2495 +} 1.2496 + 1.2497 + 1.2498 +// Return true iff the top of the operand stack holds a return address at 1.2499 +// the current instruction 1.2500 +bool GenerateOopMap::stack_top_holds_ret_addr(int bci) { 1.2501 + for(int i = 0; i < _ret_adr_tos->length(); i++) { 1.2502 + if (_ret_adr_tos->at(i) == bci) 1.2503 + return true; 1.2504 + } 1.2505 + 1.2506 + return false; 1.2507 +} 1.2508 + 1.2509 +void GenerateOopMap::compute_ret_adr_at_TOS() { 1.2510 + assert(_ret_adr_tos != NULL, "must be initialized"); 1.2511 + _ret_adr_tos->clear(); 1.2512 + 1.2513 + for (int i = 0; i < bb_count(); i++) { 1.2514 + BasicBlock* bb = &_basic_blocks[i]; 1.2515 + 1.2516 + // Make sure to only check basicblocks that are reachable 1.2517 + if (bb->is_reachable()) { 1.2518 + 1.2519 + // For each Basic block we check all instructions 1.2520 + BytecodeStream bcs(_method); 1.2521 + bcs.set_interval(bb->_bci, next_bb_start_pc(bb)); 1.2522 + 1.2523 + restore_state(bb); 1.2524 + 1.2525 + while (bcs.next()>=0 && !_got_error) { 1.2526 + // TDT: should this be is_good_address() ? 1.2527 + if (_stack_top > 0 && stack()[_stack_top-1].is_address()) { 1.2528 + _ret_adr_tos->append(bcs.bci()); 1.2529 + if (TraceNewOopMapGeneration) { 1.2530 + tty->print_cr("Ret_adr TOS at bci: %d", bcs.bci()); 1.2531 + } 1.2532 + } 1.2533 + interp1(&bcs); 1.2534 + } 1.2535 + } 1.2536 + } 1.2537 +} 1.2538 + 1.2539 +void GenerateOopMap::update_ret_adr_at_TOS(int bci, int delta) { 1.2540 + for(int i = 0; i < _ret_adr_tos->length(); i++) { 1.2541 + int v = _ret_adr_tos->at(i); 1.2542 + if (v > bci) _ret_adr_tos->at_put(i, v + delta); 1.2543 + } 1.2544 +} 1.2545 + 1.2546 +// =================================================================== 1.2547 + 1.2548 +#ifndef PRODUCT 1.2549 +int ResolveOopMapConflicts::_nof_invocations = 0; 1.2550 +int ResolveOopMapConflicts::_nof_rewrites = 0; 1.2551 +int ResolveOopMapConflicts::_nof_relocations = 0; 1.2552 +#endif 1.2553 + 1.2554 +methodHandle ResolveOopMapConflicts::do_potential_rewrite(TRAPS) { 1.2555 + compute_map(CHECK_(methodHandle())); 1.2556 + 1.2557 +#ifndef PRODUCT 1.2558 + // Tracking and statistics 1.2559 + if (PrintRewrites) { 1.2560 + _nof_invocations++; 1.2561 + if (did_rewriting()) { 1.2562 + _nof_rewrites++; 1.2563 + if (did_relocation()) _nof_relocations++; 1.2564 + tty->print("Method was rewritten %s: ", (did_relocation()) ? "and relocated" : ""); 1.2565 + method()->print_value(); tty->cr(); 1.2566 + tty->print_cr("Cand.: %d rewrts: %d (%d%%) reloc.: %d (%d%%)", 1.2567 + _nof_invocations, 1.2568 + _nof_rewrites, (_nof_rewrites * 100) / _nof_invocations, 1.2569 + _nof_relocations, (_nof_relocations * 100) / _nof_invocations); 1.2570 + } 1.2571 + } 1.2572 +#endif 1.2573 + return methodHandle(THREAD, method()); 1.2574 +}