Mon, 09 Jun 2008 11:51:19 -0400
6687581: Make CMS work with compressed oops
Summary: Make FreeChunk read markword instead of LSB in _klass pointer to indicate that it's a FreeChunk for compressed oops.
Reviewed-by: ysr, jmasa
duke@435 | 1 | /* |
duke@435 | 2 | * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
duke@435 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | * have any questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
duke@435 | 25 | // |
duke@435 | 26 | // |
duke@435 | 27 | // Compute stack layouts for each instruction in method. |
duke@435 | 28 | // |
duke@435 | 29 | // Problems: |
duke@435 | 30 | // - What to do about jsr with different types of local vars? |
duke@435 | 31 | // Need maps that are conditional on jsr path? |
duke@435 | 32 | // - Jsr and exceptions should be done more efficiently (the retAddr stuff) |
duke@435 | 33 | // |
duke@435 | 34 | // Alternative: |
duke@435 | 35 | // - Could extend verifier to provide this information. |
duke@435 | 36 | // For: one fewer abstract interpreter to maintain. Against: the verifier |
duke@435 | 37 | // solves a bigger problem so slower (undesirable to force verification of |
duke@435 | 38 | // everything?). |
duke@435 | 39 | // |
duke@435 | 40 | // Algorithm: |
duke@435 | 41 | // Partition bytecodes into basic blocks |
duke@435 | 42 | // For each basic block: store entry state (vars, stack). For instructions |
duke@435 | 43 | // inside basic blocks we do not store any state (instead we recompute it |
duke@435 | 44 | // from state produced by previous instruction). |
duke@435 | 45 | // |
duke@435 | 46 | // Perform abstract interpretation of bytecodes over this lattice: |
duke@435 | 47 | // |
duke@435 | 48 | // _--'#'--_ |
duke@435 | 49 | // / / \ \ |
duke@435 | 50 | // / / \ \ |
duke@435 | 51 | // / | | \ |
duke@435 | 52 | // 'r' 'v' 'p' ' ' |
duke@435 | 53 | // \ | | / |
duke@435 | 54 | // \ \ / / |
duke@435 | 55 | // \ \ / / |
duke@435 | 56 | // -- '@' -- |
duke@435 | 57 | // |
duke@435 | 58 | // '#' top, result of conflict merge |
duke@435 | 59 | // 'r' reference type |
duke@435 | 60 | // 'v' value type |
duke@435 | 61 | // 'p' pc type for jsr/ret |
duke@435 | 62 | // ' ' uninitialized; never occurs on operand stack in Java |
duke@435 | 63 | // '@' bottom/unexecuted; initial state each bytecode. |
duke@435 | 64 | // |
duke@435 | 65 | // Basic block headers are the only merge points. We use this iteration to |
duke@435 | 66 | // compute the information: |
duke@435 | 67 | // |
duke@435 | 68 | // find basic blocks; |
duke@435 | 69 | // initialize them with uninitialized state; |
duke@435 | 70 | // initialize first BB according to method signature; |
duke@435 | 71 | // mark first BB changed |
duke@435 | 72 | // while (some BB is changed) do { |
duke@435 | 73 | // perform abstract interpration of all bytecodes in BB; |
duke@435 | 74 | // merge exit state of BB into entry state of all successor BBs, |
duke@435 | 75 | // noting if any of these change; |
duke@435 | 76 | // } |
duke@435 | 77 | // |
duke@435 | 78 | // One additional complication is necessary. The jsr instruction pushes |
duke@435 | 79 | // a return PC on the stack (a 'p' type in the abstract interpretation). |
duke@435 | 80 | // To be able to process "ret" bytecodes, we keep track of these return |
duke@435 | 81 | // PC's in a 'retAddrs' structure in abstract interpreter context (when |
duke@435 | 82 | // processing a "ret" bytecodes, it is not sufficient to know that it gets |
duke@435 | 83 | // an argument of the right type 'p'; we need to know which address it |
duke@435 | 84 | // returns to). |
duke@435 | 85 | // |
duke@435 | 86 | // (Note this comment is borrowed form the original author of the algorithm) |
duke@435 | 87 | |
duke@435 | 88 | #include "incls/_precompiled.incl" |
duke@435 | 89 | #include "incls/_generateOopMap.cpp.incl" |
duke@435 | 90 | |
duke@435 | 91 | // ComputeCallStack |
duke@435 | 92 | // |
duke@435 | 93 | // Specialization of SignatureIterator - compute the effects of a call |
duke@435 | 94 | // |
duke@435 | 95 | class ComputeCallStack : public SignatureIterator { |
duke@435 | 96 | CellTypeState *_effect; |
duke@435 | 97 | int _idx; |
duke@435 | 98 | |
duke@435 | 99 | void setup(); |
duke@435 | 100 | void set(CellTypeState state) { _effect[_idx++] = state; } |
duke@435 | 101 | int length() { return _idx; }; |
duke@435 | 102 | |
duke@435 | 103 | virtual void do_bool () { set(CellTypeState::value); }; |
duke@435 | 104 | virtual void do_char () { set(CellTypeState::value); }; |
duke@435 | 105 | virtual void do_float () { set(CellTypeState::value); }; |
duke@435 | 106 | virtual void do_byte () { set(CellTypeState::value); }; |
duke@435 | 107 | virtual void do_short () { set(CellTypeState::value); }; |
duke@435 | 108 | virtual void do_int () { set(CellTypeState::value); }; |
duke@435 | 109 | virtual void do_void () { set(CellTypeState::bottom);}; |
duke@435 | 110 | virtual void do_object(int begin, int end) { set(CellTypeState::ref); }; |
duke@435 | 111 | virtual void do_array (int begin, int end) { set(CellTypeState::ref); }; |
duke@435 | 112 | |
duke@435 | 113 | void do_double() { set(CellTypeState::value); |
duke@435 | 114 | set(CellTypeState::value); } |
duke@435 | 115 | void do_long () { set(CellTypeState::value); |
duke@435 | 116 | set(CellTypeState::value); } |
duke@435 | 117 | |
duke@435 | 118 | public: |
duke@435 | 119 | ComputeCallStack(symbolOop signature) : SignatureIterator(signature) {}; |
duke@435 | 120 | |
duke@435 | 121 | // Compute methods |
duke@435 | 122 | int compute_for_parameters(bool is_static, CellTypeState *effect) { |
duke@435 | 123 | _idx = 0; |
duke@435 | 124 | _effect = effect; |
duke@435 | 125 | |
duke@435 | 126 | if (!is_static) |
duke@435 | 127 | effect[_idx++] = CellTypeState::ref; |
duke@435 | 128 | |
duke@435 | 129 | iterate_parameters(); |
duke@435 | 130 | |
duke@435 | 131 | return length(); |
duke@435 | 132 | }; |
duke@435 | 133 | |
duke@435 | 134 | int compute_for_returntype(CellTypeState *effect) { |
duke@435 | 135 | _idx = 0; |
duke@435 | 136 | _effect = effect; |
duke@435 | 137 | iterate_returntype(); |
duke@435 | 138 | set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works |
duke@435 | 139 | |
duke@435 | 140 | return length(); |
duke@435 | 141 | } |
duke@435 | 142 | }; |
duke@435 | 143 | |
duke@435 | 144 | //========================================================================================= |
duke@435 | 145 | // ComputeEntryStack |
duke@435 | 146 | // |
duke@435 | 147 | // Specialization of SignatureIterator - in order to set up first stack frame |
duke@435 | 148 | // |
duke@435 | 149 | class ComputeEntryStack : public SignatureIterator { |
duke@435 | 150 | CellTypeState *_effect; |
duke@435 | 151 | int _idx; |
duke@435 | 152 | |
duke@435 | 153 | void setup(); |
duke@435 | 154 | void set(CellTypeState state) { _effect[_idx++] = state; } |
duke@435 | 155 | int length() { return _idx; }; |
duke@435 | 156 | |
duke@435 | 157 | virtual void do_bool () { set(CellTypeState::value); }; |
duke@435 | 158 | virtual void do_char () { set(CellTypeState::value); }; |
duke@435 | 159 | virtual void do_float () { set(CellTypeState::value); }; |
duke@435 | 160 | virtual void do_byte () { set(CellTypeState::value); }; |
duke@435 | 161 | virtual void do_short () { set(CellTypeState::value); }; |
duke@435 | 162 | virtual void do_int () { set(CellTypeState::value); }; |
duke@435 | 163 | virtual void do_void () { set(CellTypeState::bottom);}; |
duke@435 | 164 | virtual void do_object(int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } |
duke@435 | 165 | virtual void do_array (int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } |
duke@435 | 166 | |
duke@435 | 167 | void do_double() { set(CellTypeState::value); |
duke@435 | 168 | set(CellTypeState::value); } |
duke@435 | 169 | void do_long () { set(CellTypeState::value); |
duke@435 | 170 | set(CellTypeState::value); } |
duke@435 | 171 | |
duke@435 | 172 | public: |
duke@435 | 173 | ComputeEntryStack(symbolOop signature) : SignatureIterator(signature) {}; |
duke@435 | 174 | |
duke@435 | 175 | // Compute methods |
duke@435 | 176 | int compute_for_parameters(bool is_static, CellTypeState *effect) { |
duke@435 | 177 | _idx = 0; |
duke@435 | 178 | _effect = effect; |
duke@435 | 179 | |
duke@435 | 180 | if (!is_static) |
duke@435 | 181 | effect[_idx++] = CellTypeState::make_slot_ref(0); |
duke@435 | 182 | |
duke@435 | 183 | iterate_parameters(); |
duke@435 | 184 | |
duke@435 | 185 | return length(); |
duke@435 | 186 | }; |
duke@435 | 187 | |
duke@435 | 188 | int compute_for_returntype(CellTypeState *effect) { |
duke@435 | 189 | _idx = 0; |
duke@435 | 190 | _effect = effect; |
duke@435 | 191 | iterate_returntype(); |
duke@435 | 192 | set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works |
duke@435 | 193 | |
duke@435 | 194 | return length(); |
duke@435 | 195 | } |
duke@435 | 196 | }; |
duke@435 | 197 | |
duke@435 | 198 | //===================================================================================== |
duke@435 | 199 | // |
duke@435 | 200 | // Implementation of RetTable/RetTableEntry |
duke@435 | 201 | // |
duke@435 | 202 | // Contains function to itereate through all bytecodes |
duke@435 | 203 | // and find all return entry points |
duke@435 | 204 | // |
duke@435 | 205 | int RetTable::_init_nof_entries = 10; |
duke@435 | 206 | int RetTableEntry::_init_nof_jsrs = 5; |
duke@435 | 207 | |
duke@435 | 208 | void RetTableEntry::add_delta(int bci, int delta) { |
duke@435 | 209 | if (_target_bci > bci) _target_bci += delta; |
duke@435 | 210 | |
duke@435 | 211 | for (int k = 0; k < _jsrs->length(); k++) { |
duke@435 | 212 | int jsr = _jsrs->at(k); |
duke@435 | 213 | if (jsr > bci) _jsrs->at_put(k, jsr+delta); |
duke@435 | 214 | } |
duke@435 | 215 | } |
duke@435 | 216 | |
duke@435 | 217 | void RetTable::compute_ret_table(methodHandle method) { |
duke@435 | 218 | BytecodeStream i(method); |
duke@435 | 219 | Bytecodes::Code bytecode; |
duke@435 | 220 | |
duke@435 | 221 | while( (bytecode = i.next()) >= 0) { |
duke@435 | 222 | switch (bytecode) { |
duke@435 | 223 | case Bytecodes::_jsr: |
duke@435 | 224 | add_jsr(i.next_bci(), i.dest()); |
duke@435 | 225 | break; |
duke@435 | 226 | case Bytecodes::_jsr_w: |
duke@435 | 227 | add_jsr(i.next_bci(), i.dest_w()); |
duke@435 | 228 | break; |
duke@435 | 229 | } |
duke@435 | 230 | } |
duke@435 | 231 | } |
duke@435 | 232 | |
duke@435 | 233 | void RetTable::add_jsr(int return_bci, int target_bci) { |
duke@435 | 234 | RetTableEntry* entry = _first; |
duke@435 | 235 | |
duke@435 | 236 | // Scan table for entry |
duke@435 | 237 | for (;entry && entry->target_bci() != target_bci; entry = entry->next()); |
duke@435 | 238 | |
duke@435 | 239 | if (!entry) { |
duke@435 | 240 | // Allocate new entry and put in list |
duke@435 | 241 | entry = new RetTableEntry(target_bci, _first); |
duke@435 | 242 | _first = entry; |
duke@435 | 243 | } |
duke@435 | 244 | |
duke@435 | 245 | // Now "entry" is set. Make sure that the entry is initialized |
duke@435 | 246 | // and has room for the new jsr. |
duke@435 | 247 | entry->add_jsr(return_bci); |
duke@435 | 248 | } |
duke@435 | 249 | |
duke@435 | 250 | RetTableEntry* RetTable::find_jsrs_for_target(int targBci) { |
duke@435 | 251 | RetTableEntry *cur = _first; |
duke@435 | 252 | |
duke@435 | 253 | while(cur) { |
duke@435 | 254 | assert(cur->target_bci() != -1, "sanity check"); |
duke@435 | 255 | if (cur->target_bci() == targBci) return cur; |
duke@435 | 256 | cur = cur->next(); |
duke@435 | 257 | } |
duke@435 | 258 | ShouldNotReachHere(); |
duke@435 | 259 | return NULL; |
duke@435 | 260 | } |
duke@435 | 261 | |
duke@435 | 262 | // The instruction at bci is changing size by "delta". Update the return map. |
duke@435 | 263 | void RetTable::update_ret_table(int bci, int delta) { |
duke@435 | 264 | RetTableEntry *cur = _first; |
duke@435 | 265 | while(cur) { |
duke@435 | 266 | cur->add_delta(bci, delta); |
duke@435 | 267 | cur = cur->next(); |
duke@435 | 268 | } |
duke@435 | 269 | } |
duke@435 | 270 | |
duke@435 | 271 | // |
duke@435 | 272 | // Celltype state |
duke@435 | 273 | // |
duke@435 | 274 | |
duke@435 | 275 | CellTypeState CellTypeState::bottom = CellTypeState::make_bottom(); |
duke@435 | 276 | CellTypeState CellTypeState::uninit = CellTypeState::make_any(uninit_value); |
duke@435 | 277 | CellTypeState CellTypeState::ref = CellTypeState::make_any(ref_conflict); |
duke@435 | 278 | CellTypeState CellTypeState::value = CellTypeState::make_any(val_value); |
duke@435 | 279 | CellTypeState CellTypeState::refUninit = CellTypeState::make_any(ref_conflict | uninit_value); |
duke@435 | 280 | CellTypeState CellTypeState::top = CellTypeState::make_top(); |
duke@435 | 281 | CellTypeState CellTypeState::addr = CellTypeState::make_any(addr_conflict); |
duke@435 | 282 | |
duke@435 | 283 | // Commonly used constants |
duke@435 | 284 | static CellTypeState epsilonCTS[1] = { CellTypeState::bottom }; |
duke@435 | 285 | static CellTypeState refCTS = CellTypeState::ref; |
duke@435 | 286 | static CellTypeState valCTS = CellTypeState::value; |
duke@435 | 287 | static CellTypeState vCTS[2] = { CellTypeState::value, CellTypeState::bottom }; |
duke@435 | 288 | static CellTypeState rCTS[2] = { CellTypeState::ref, CellTypeState::bottom }; |
duke@435 | 289 | static CellTypeState rrCTS[3] = { CellTypeState::ref, CellTypeState::ref, CellTypeState::bottom }; |
duke@435 | 290 | static CellTypeState vrCTS[3] = { CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; |
duke@435 | 291 | static CellTypeState vvCTS[3] = { CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; |
duke@435 | 292 | static CellTypeState rvrCTS[4] = { CellTypeState::ref, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; |
duke@435 | 293 | static CellTypeState vvrCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; |
duke@435 | 294 | static CellTypeState vvvCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; |
duke@435 | 295 | static CellTypeState vvvrCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; |
duke@435 | 296 | static CellTypeState vvvvCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; |
duke@435 | 297 | |
duke@435 | 298 | char CellTypeState::to_char() const { |
duke@435 | 299 | if (can_be_reference()) { |
duke@435 | 300 | if (can_be_value() || can_be_address()) |
duke@435 | 301 | return '#'; // Conflict that needs to be rewritten |
duke@435 | 302 | else |
duke@435 | 303 | return 'r'; |
duke@435 | 304 | } else if (can_be_value()) |
duke@435 | 305 | return 'v'; |
duke@435 | 306 | else if (can_be_address()) |
duke@435 | 307 | return 'p'; |
duke@435 | 308 | else if (can_be_uninit()) |
duke@435 | 309 | return ' '; |
duke@435 | 310 | else |
duke@435 | 311 | return '@'; |
duke@435 | 312 | } |
duke@435 | 313 | |
duke@435 | 314 | |
duke@435 | 315 | // Print a detailed CellTypeState. Indicate all bits that are set. If |
duke@435 | 316 | // the CellTypeState represents an address or a reference, print the |
duke@435 | 317 | // value of the additional information. |
duke@435 | 318 | void CellTypeState::print(outputStream *os) { |
duke@435 | 319 | if (can_be_address()) { |
duke@435 | 320 | os->print("(p"); |
duke@435 | 321 | } else { |
duke@435 | 322 | os->print("( "); |
duke@435 | 323 | } |
duke@435 | 324 | if (can_be_reference()) { |
duke@435 | 325 | os->print("r"); |
duke@435 | 326 | } else { |
duke@435 | 327 | os->print(" "); |
duke@435 | 328 | } |
duke@435 | 329 | if (can_be_value()) { |
duke@435 | 330 | os->print("v"); |
duke@435 | 331 | } else { |
duke@435 | 332 | os->print(" "); |
duke@435 | 333 | } |
duke@435 | 334 | if (can_be_uninit()) { |
duke@435 | 335 | os->print("u|"); |
duke@435 | 336 | } else { |
duke@435 | 337 | os->print(" |"); |
duke@435 | 338 | } |
duke@435 | 339 | if (is_info_top()) { |
duke@435 | 340 | os->print("Top)"); |
duke@435 | 341 | } else if (is_info_bottom()) { |
duke@435 | 342 | os->print("Bot)"); |
duke@435 | 343 | } else { |
duke@435 | 344 | if (is_reference()) { |
duke@435 | 345 | int info = get_info(); |
duke@435 | 346 | int data = info & ~(ref_not_lock_bit | ref_slot_bit); |
duke@435 | 347 | if (info & ref_not_lock_bit) { |
duke@435 | 348 | // Not a monitor lock reference. |
duke@435 | 349 | if (info & ref_slot_bit) { |
duke@435 | 350 | // slot |
duke@435 | 351 | os->print("slot%d)", data); |
duke@435 | 352 | } else { |
duke@435 | 353 | // line |
duke@435 | 354 | os->print("line%d)", data); |
duke@435 | 355 | } |
duke@435 | 356 | } else { |
duke@435 | 357 | // lock |
duke@435 | 358 | os->print("lock%d)", data); |
duke@435 | 359 | } |
duke@435 | 360 | } else { |
duke@435 | 361 | os->print("%d)", get_info()); |
duke@435 | 362 | } |
duke@435 | 363 | } |
duke@435 | 364 | } |
duke@435 | 365 | |
duke@435 | 366 | // |
duke@435 | 367 | // Basicblock handling methods |
duke@435 | 368 | // |
duke@435 | 369 | |
duke@435 | 370 | void GenerateOopMap ::initialize_bb() { |
duke@435 | 371 | _gc_points = 0; |
duke@435 | 372 | _bb_count = 0; |
duke@435 | 373 | int size = binsToHold(method()->code_size()); |
duke@435 | 374 | _bb_hdr_bits = NEW_RESOURCE_ARRAY(uintptr_t,size); |
duke@435 | 375 | memset(_bb_hdr_bits, 0, size*sizeof(uintptr_t)); |
duke@435 | 376 | } |
duke@435 | 377 | |
duke@435 | 378 | void GenerateOopMap ::set_bbmark_bit(int bci) { |
duke@435 | 379 | int idx = bci >> LogBitsPerWord; |
duke@435 | 380 | uintptr_t bit = (uintptr_t)1 << (bci & (BitsPerWord-1)); |
duke@435 | 381 | _bb_hdr_bits[idx] |= bit; |
duke@435 | 382 | } |
duke@435 | 383 | |
duke@435 | 384 | void GenerateOopMap ::clear_bbmark_bit(int bci) { |
duke@435 | 385 | int idx = bci >> LogBitsPerWord; |
duke@435 | 386 | uintptr_t bit = (uintptr_t)1 << (bci & (BitsPerWord-1)); |
duke@435 | 387 | _bb_hdr_bits[idx] &= (~bit); |
duke@435 | 388 | } |
duke@435 | 389 | |
duke@435 | 390 | void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) { |
duke@435 | 391 | assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds"); |
duke@435 | 392 | if (c->is_bb_header(bci)) |
duke@435 | 393 | return; |
duke@435 | 394 | |
duke@435 | 395 | if (TraceNewOopMapGeneration) { |
duke@435 | 396 | tty->print_cr("Basicblock#%d begins at: %d", c->_bb_count, bci); |
duke@435 | 397 | } |
duke@435 | 398 | c->set_bbmark_bit(bci); |
duke@435 | 399 | c->_bb_count++; |
duke@435 | 400 | } |
duke@435 | 401 | |
duke@435 | 402 | |
duke@435 | 403 | void GenerateOopMap::mark_bbheaders_and_count_gc_points() { |
duke@435 | 404 | initialize_bb(); |
duke@435 | 405 | |
duke@435 | 406 | bool fellThrough = false; // False to get first BB marked. |
duke@435 | 407 | |
duke@435 | 408 | // First mark all exception handlers as start of a basic-block |
duke@435 | 409 | typeArrayOop excps = method()->exception_table(); |
duke@435 | 410 | for(int i = 0; i < excps->length(); i += 4) { |
duke@435 | 411 | int handler_pc_idx = i+2; |
duke@435 | 412 | bb_mark_fct(this, excps->int_at(handler_pc_idx), NULL); |
duke@435 | 413 | } |
duke@435 | 414 | |
duke@435 | 415 | // Then iterate through the code |
duke@435 | 416 | BytecodeStream bcs(_method); |
duke@435 | 417 | Bytecodes::Code bytecode; |
duke@435 | 418 | |
duke@435 | 419 | while( (bytecode = bcs.next()) >= 0) { |
duke@435 | 420 | int bci = bcs.bci(); |
duke@435 | 421 | |
duke@435 | 422 | if (!fellThrough) |
duke@435 | 423 | bb_mark_fct(this, bci, NULL); |
duke@435 | 424 | |
duke@435 | 425 | fellThrough = jump_targets_do(&bcs, &GenerateOopMap::bb_mark_fct, NULL); |
duke@435 | 426 | |
duke@435 | 427 | /* We will also mark successors of jsr's as basic block headers. */ |
duke@435 | 428 | switch (bytecode) { |
duke@435 | 429 | case Bytecodes::_jsr: |
duke@435 | 430 | assert(!fellThrough, "should not happen"); |
duke@435 | 431 | bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL); |
duke@435 | 432 | break; |
duke@435 | 433 | case Bytecodes::_jsr_w: |
duke@435 | 434 | assert(!fellThrough, "should not happen"); |
duke@435 | 435 | bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL); |
duke@435 | 436 | break; |
duke@435 | 437 | } |
duke@435 | 438 | |
duke@435 | 439 | if (possible_gc_point(&bcs)) |
duke@435 | 440 | _gc_points++; |
duke@435 | 441 | } |
duke@435 | 442 | } |
duke@435 | 443 | |
duke@435 | 444 | void GenerateOopMap::reachable_basicblock(GenerateOopMap *c, int bci, int *data) { |
duke@435 | 445 | assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds"); |
duke@435 | 446 | BasicBlock* bb = c->get_basic_block_at(bci); |
duke@435 | 447 | if (bb->is_dead()) { |
duke@435 | 448 | bb->mark_as_alive(); |
duke@435 | 449 | *data = 1; // Mark basicblock as changed |
duke@435 | 450 | } |
duke@435 | 451 | } |
duke@435 | 452 | |
duke@435 | 453 | |
duke@435 | 454 | void GenerateOopMap::mark_reachable_code() { |
duke@435 | 455 | int change = 1; // int to get function pointers to work |
duke@435 | 456 | |
duke@435 | 457 | // Mark entry basic block as alive and all exception handlers |
duke@435 | 458 | _basic_blocks[0].mark_as_alive(); |
duke@435 | 459 | typeArrayOop excps = method()->exception_table(); |
duke@435 | 460 | for(int i = 0; i < excps->length(); i += 4) { |
duke@435 | 461 | int handler_pc_idx = i+2; |
duke@435 | 462 | BasicBlock *bb = get_basic_block_at(excps->int_at(handler_pc_idx)); |
duke@435 | 463 | // If block is not already alive (due to multiple exception handlers to same bb), then |
duke@435 | 464 | // make it alive |
duke@435 | 465 | if (bb->is_dead()) bb->mark_as_alive(); |
duke@435 | 466 | } |
duke@435 | 467 | |
duke@435 | 468 | BytecodeStream bcs(_method); |
duke@435 | 469 | |
duke@435 | 470 | // Iterate through all basic blocks until we reach a fixpoint |
duke@435 | 471 | while (change) { |
duke@435 | 472 | change = 0; |
duke@435 | 473 | |
duke@435 | 474 | for (int i = 0; i < _bb_count; i++) { |
duke@435 | 475 | BasicBlock *bb = &_basic_blocks[i]; |
duke@435 | 476 | if (bb->is_alive()) { |
duke@435 | 477 | // Position bytecodestream at last bytecode in basicblock |
duke@435 | 478 | bcs.set_start(bb->_end_bci); |
duke@435 | 479 | bcs.next(); |
duke@435 | 480 | Bytecodes::Code bytecode = bcs.code(); |
duke@435 | 481 | int bci = bcs.bci(); |
duke@435 | 482 | assert(bci == bb->_end_bci, "wrong bci"); |
duke@435 | 483 | |
duke@435 | 484 | bool fell_through = jump_targets_do(&bcs, &GenerateOopMap::reachable_basicblock, &change); |
duke@435 | 485 | |
duke@435 | 486 | // We will also mark successors of jsr's as alive. |
duke@435 | 487 | switch (bytecode) { |
duke@435 | 488 | case Bytecodes::_jsr: |
duke@435 | 489 | case Bytecodes::_jsr_w: |
duke@435 | 490 | assert(!fell_through, "should not happen"); |
duke@435 | 491 | reachable_basicblock(this, bci + Bytecodes::length_for(bytecode), &change); |
duke@435 | 492 | break; |
duke@435 | 493 | } |
duke@435 | 494 | if (fell_through) { |
duke@435 | 495 | // Mark successor as alive |
duke@435 | 496 | if (bb[1].is_dead()) { |
duke@435 | 497 | bb[1].mark_as_alive(); |
duke@435 | 498 | change = 1; |
duke@435 | 499 | } |
duke@435 | 500 | } |
duke@435 | 501 | } |
duke@435 | 502 | } |
duke@435 | 503 | } |
duke@435 | 504 | } |
duke@435 | 505 | |
duke@435 | 506 | /* If the current instruction in "c" has no effect on control flow, |
duke@435 | 507 | returns "true". Otherwise, calls "jmpFct" one or more times, with |
duke@435 | 508 | "c", an appropriate "pcDelta", and "data" as arguments, then |
duke@435 | 509 | returns "false". There is one exception: if the current |
duke@435 | 510 | instruction is a "ret", returns "false" without calling "jmpFct". |
duke@435 | 511 | Arrangements for tracking the control flow of a "ret" must be made |
duke@435 | 512 | externally. */ |
duke@435 | 513 | bool GenerateOopMap::jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int *data) { |
duke@435 | 514 | int bci = bcs->bci(); |
duke@435 | 515 | |
duke@435 | 516 | switch (bcs->code()) { |
duke@435 | 517 | case Bytecodes::_ifeq: |
duke@435 | 518 | case Bytecodes::_ifne: |
duke@435 | 519 | case Bytecodes::_iflt: |
duke@435 | 520 | case Bytecodes::_ifge: |
duke@435 | 521 | case Bytecodes::_ifgt: |
duke@435 | 522 | case Bytecodes::_ifle: |
duke@435 | 523 | case Bytecodes::_if_icmpeq: |
duke@435 | 524 | case Bytecodes::_if_icmpne: |
duke@435 | 525 | case Bytecodes::_if_icmplt: |
duke@435 | 526 | case Bytecodes::_if_icmpge: |
duke@435 | 527 | case Bytecodes::_if_icmpgt: |
duke@435 | 528 | case Bytecodes::_if_icmple: |
duke@435 | 529 | case Bytecodes::_if_acmpeq: |
duke@435 | 530 | case Bytecodes::_if_acmpne: |
duke@435 | 531 | case Bytecodes::_ifnull: |
duke@435 | 532 | case Bytecodes::_ifnonnull: |
duke@435 | 533 | (*jmpFct)(this, bcs->dest(), data); |
duke@435 | 534 | (*jmpFct)(this, bci + 3, data); |
duke@435 | 535 | break; |
duke@435 | 536 | |
duke@435 | 537 | case Bytecodes::_goto: |
duke@435 | 538 | (*jmpFct)(this, bcs->dest(), data); |
duke@435 | 539 | break; |
duke@435 | 540 | case Bytecodes::_goto_w: |
duke@435 | 541 | (*jmpFct)(this, bcs->dest_w(), data); |
duke@435 | 542 | break; |
duke@435 | 543 | case Bytecodes::_tableswitch: |
duke@435 | 544 | { Bytecode_tableswitch *tableswitch = Bytecode_tableswitch_at(bcs->bcp()); |
duke@435 | 545 | int len = tableswitch->length(); |
duke@435 | 546 | |
duke@435 | 547 | (*jmpFct)(this, bci + tableswitch->default_offset(), data); /* Default. jump address */ |
duke@435 | 548 | while (--len >= 0) { |
duke@435 | 549 | (*jmpFct)(this, bci + tableswitch->dest_offset_at(len), data); |
duke@435 | 550 | } |
duke@435 | 551 | break; |
duke@435 | 552 | } |
duke@435 | 553 | |
duke@435 | 554 | case Bytecodes::_lookupswitch: |
duke@435 | 555 | { Bytecode_lookupswitch *lookupswitch = Bytecode_lookupswitch_at(bcs->bcp()); |
duke@435 | 556 | int npairs = lookupswitch->number_of_pairs(); |
duke@435 | 557 | (*jmpFct)(this, bci + lookupswitch->default_offset(), data); /* Default. */ |
duke@435 | 558 | while(--npairs >= 0) { |
duke@435 | 559 | LookupswitchPair *pair = lookupswitch->pair_at(npairs); |
duke@435 | 560 | (*jmpFct)(this, bci + pair->offset(), data); |
duke@435 | 561 | } |
duke@435 | 562 | break; |
duke@435 | 563 | } |
duke@435 | 564 | case Bytecodes::_jsr: |
duke@435 | 565 | assert(bcs->is_wide()==false, "sanity check"); |
duke@435 | 566 | (*jmpFct)(this, bcs->dest(), data); |
duke@435 | 567 | |
duke@435 | 568 | |
duke@435 | 569 | |
duke@435 | 570 | break; |
duke@435 | 571 | case Bytecodes::_jsr_w: |
duke@435 | 572 | (*jmpFct)(this, bcs->dest_w(), data); |
duke@435 | 573 | break; |
duke@435 | 574 | case Bytecodes::_wide: |
duke@435 | 575 | ShouldNotReachHere(); |
duke@435 | 576 | return true; |
duke@435 | 577 | break; |
duke@435 | 578 | case Bytecodes::_athrow: |
duke@435 | 579 | case Bytecodes::_ireturn: |
duke@435 | 580 | case Bytecodes::_lreturn: |
duke@435 | 581 | case Bytecodes::_freturn: |
duke@435 | 582 | case Bytecodes::_dreturn: |
duke@435 | 583 | case Bytecodes::_areturn: |
duke@435 | 584 | case Bytecodes::_return: |
duke@435 | 585 | case Bytecodes::_ret: |
duke@435 | 586 | break; |
duke@435 | 587 | default: |
duke@435 | 588 | return true; |
duke@435 | 589 | } |
duke@435 | 590 | return false; |
duke@435 | 591 | } |
duke@435 | 592 | |
duke@435 | 593 | /* Requires "pc" to be the head of a basic block; returns that basic |
duke@435 | 594 | block. */ |
duke@435 | 595 | BasicBlock *GenerateOopMap::get_basic_block_at(int bci) const { |
duke@435 | 596 | BasicBlock* bb = get_basic_block_containing(bci); |
duke@435 | 597 | assert(bb->_bci == bci, "should have found BB"); |
duke@435 | 598 | return bb; |
duke@435 | 599 | } |
duke@435 | 600 | |
duke@435 | 601 | // Requires "pc" to be the start of an instruction; returns the basic |
duke@435 | 602 | // block containing that instruction. */ |
duke@435 | 603 | BasicBlock *GenerateOopMap::get_basic_block_containing(int bci) const { |
duke@435 | 604 | BasicBlock *bbs = _basic_blocks; |
duke@435 | 605 | int lo = 0, hi = _bb_count - 1; |
duke@435 | 606 | |
duke@435 | 607 | while (lo <= hi) { |
duke@435 | 608 | int m = (lo + hi) / 2; |
duke@435 | 609 | int mbci = bbs[m]._bci; |
duke@435 | 610 | int nbci; |
duke@435 | 611 | |
duke@435 | 612 | if ( m == _bb_count-1) { |
duke@435 | 613 | assert( bci >= mbci && bci < method()->code_size(), "sanity check failed"); |
duke@435 | 614 | return bbs+m; |
duke@435 | 615 | } else { |
duke@435 | 616 | nbci = bbs[m+1]._bci; |
duke@435 | 617 | } |
duke@435 | 618 | |
duke@435 | 619 | if ( mbci <= bci && bci < nbci) { |
duke@435 | 620 | return bbs+m; |
duke@435 | 621 | } else if (mbci < bci) { |
duke@435 | 622 | lo = m + 1; |
duke@435 | 623 | } else { |
duke@435 | 624 | assert(mbci > bci, "sanity check"); |
duke@435 | 625 | hi = m - 1; |
duke@435 | 626 | } |
duke@435 | 627 | } |
duke@435 | 628 | |
duke@435 | 629 | fatal("should have found BB"); |
duke@435 | 630 | return NULL; |
duke@435 | 631 | } |
duke@435 | 632 | |
duke@435 | 633 | void GenerateOopMap::restore_state(BasicBlock *bb) |
duke@435 | 634 | { |
duke@435 | 635 | memcpy(_state, bb->_state, _state_len*sizeof(CellTypeState)); |
duke@435 | 636 | _stack_top = bb->_stack_top; |
duke@435 | 637 | _monitor_top = bb->_monitor_top; |
duke@435 | 638 | } |
duke@435 | 639 | |
duke@435 | 640 | int GenerateOopMap::next_bb_start_pc(BasicBlock *bb) { |
duke@435 | 641 | int bbNum = bb - _basic_blocks + 1; |
duke@435 | 642 | if (bbNum == _bb_count) |
duke@435 | 643 | return method()->code_size(); |
duke@435 | 644 | |
duke@435 | 645 | return _basic_blocks[bbNum]._bci; |
duke@435 | 646 | } |
duke@435 | 647 | |
duke@435 | 648 | // |
duke@435 | 649 | // CellType handling methods |
duke@435 | 650 | // |
duke@435 | 651 | |
duke@435 | 652 | void GenerateOopMap::init_state() { |
duke@435 | 653 | _state_len = _max_locals + _max_stack + _max_monitors; |
duke@435 | 654 | _state = NEW_RESOURCE_ARRAY(CellTypeState, _state_len); |
duke@435 | 655 | memset(_state, 0, _state_len * sizeof(CellTypeState)); |
duke@435 | 656 | _state_vec_buf = NEW_RESOURCE_ARRAY(char, MAX3(_max_locals, _max_stack, _max_monitors) + 1/*for null terminator char */); |
duke@435 | 657 | } |
duke@435 | 658 | |
duke@435 | 659 | void GenerateOopMap::make_context_uninitialized() { |
duke@435 | 660 | CellTypeState* vs = vars(); |
duke@435 | 661 | |
duke@435 | 662 | for (int i = 0; i < _max_locals; i++) |
duke@435 | 663 | vs[i] = CellTypeState::uninit; |
duke@435 | 664 | |
duke@435 | 665 | _stack_top = 0; |
duke@435 | 666 | _monitor_top = 0; |
duke@435 | 667 | } |
duke@435 | 668 | |
duke@435 | 669 | int GenerateOopMap::methodsig_to_effect(symbolOop signature, bool is_static, CellTypeState* effect) { |
duke@435 | 670 | ComputeEntryStack ces(signature); |
duke@435 | 671 | return ces.compute_for_parameters(is_static, effect); |
duke@435 | 672 | } |
duke@435 | 673 | |
duke@435 | 674 | // Return result of merging cts1 and cts2. |
duke@435 | 675 | CellTypeState CellTypeState::merge(CellTypeState cts, int slot) const { |
duke@435 | 676 | CellTypeState result; |
duke@435 | 677 | |
duke@435 | 678 | assert(!is_bottom() && !cts.is_bottom(), |
duke@435 | 679 | "merge of bottom values is handled elsewhere"); |
duke@435 | 680 | |
duke@435 | 681 | result._state = _state | cts._state; |
duke@435 | 682 | |
duke@435 | 683 | // If the top bit is set, we don't need to do any more work. |
duke@435 | 684 | if (!result.is_info_top()) { |
duke@435 | 685 | assert((result.can_be_address() || result.can_be_reference()), |
duke@435 | 686 | "only addresses and references have non-top info"); |
duke@435 | 687 | |
duke@435 | 688 | if (!equal(cts)) { |
duke@435 | 689 | // The two values being merged are different. Raise to top. |
duke@435 | 690 | if (result.is_reference()) { |
duke@435 | 691 | result = CellTypeState::make_slot_ref(slot); |
duke@435 | 692 | } else { |
duke@435 | 693 | result._state |= info_conflict; |
duke@435 | 694 | } |
duke@435 | 695 | } |
duke@435 | 696 | } |
duke@435 | 697 | assert(result.is_valid_state(), "checking that CTS merge maintains legal state"); |
duke@435 | 698 | |
duke@435 | 699 | return result; |
duke@435 | 700 | } |
duke@435 | 701 | |
duke@435 | 702 | // Merge the variable state for locals and stack from cts into bbts. |
duke@435 | 703 | bool GenerateOopMap::merge_local_state_vectors(CellTypeState* cts, |
duke@435 | 704 | CellTypeState* bbts) { |
duke@435 | 705 | int i; |
duke@435 | 706 | int len = _max_locals + _stack_top; |
duke@435 | 707 | bool change = false; |
duke@435 | 708 | |
duke@435 | 709 | for (i = len - 1; i >= 0; i--) { |
duke@435 | 710 | CellTypeState v = cts[i].merge(bbts[i], i); |
duke@435 | 711 | change = change || !v.equal(bbts[i]); |
duke@435 | 712 | bbts[i] = v; |
duke@435 | 713 | } |
duke@435 | 714 | |
duke@435 | 715 | return change; |
duke@435 | 716 | } |
duke@435 | 717 | |
duke@435 | 718 | // Merge the monitor stack state from cts into bbts. |
duke@435 | 719 | bool GenerateOopMap::merge_monitor_state_vectors(CellTypeState* cts, |
duke@435 | 720 | CellTypeState* bbts) { |
duke@435 | 721 | bool change = false; |
duke@435 | 722 | if (_max_monitors > 0 && _monitor_top != bad_monitors) { |
duke@435 | 723 | // If there are no monitors in the program, or there has been |
duke@435 | 724 | // a monitor matching error before this point in the program, |
duke@435 | 725 | // then we do not merge in the monitor state. |
duke@435 | 726 | |
duke@435 | 727 | int base = _max_locals + _max_stack; |
duke@435 | 728 | int len = base + _monitor_top; |
duke@435 | 729 | for (int i = len - 1; i >= base; i--) { |
duke@435 | 730 | CellTypeState v = cts[i].merge(bbts[i], i); |
duke@435 | 731 | |
duke@435 | 732 | // Can we prove that, when there has been a change, it will already |
duke@435 | 733 | // have been detected at this point? That would make this equal |
duke@435 | 734 | // check here unnecessary. |
duke@435 | 735 | change = change || !v.equal(bbts[i]); |
duke@435 | 736 | bbts[i] = v; |
duke@435 | 737 | } |
duke@435 | 738 | } |
duke@435 | 739 | |
duke@435 | 740 | return change; |
duke@435 | 741 | } |
duke@435 | 742 | |
duke@435 | 743 | void GenerateOopMap::copy_state(CellTypeState *dst, CellTypeState *src) { |
duke@435 | 744 | int len = _max_locals + _stack_top; |
duke@435 | 745 | for (int i = 0; i < len; i++) { |
duke@435 | 746 | if (src[i].is_nonlock_reference()) { |
duke@435 | 747 | dst[i] = CellTypeState::make_slot_ref(i); |
duke@435 | 748 | } else { |
duke@435 | 749 | dst[i] = src[i]; |
duke@435 | 750 | } |
duke@435 | 751 | } |
duke@435 | 752 | if (_max_monitors > 0 && _monitor_top != bad_monitors) { |
duke@435 | 753 | int base = _max_locals + _max_stack; |
duke@435 | 754 | len = base + _monitor_top; |
duke@435 | 755 | for (int i = base; i < len; i++) { |
duke@435 | 756 | dst[i] = src[i]; |
duke@435 | 757 | } |
duke@435 | 758 | } |
duke@435 | 759 | } |
duke@435 | 760 | |
duke@435 | 761 | |
duke@435 | 762 | // Merge the states for the current block and the next. As long as a |
duke@435 | 763 | // block is reachable the locals and stack must be merged. If the |
duke@435 | 764 | // stack heights don't match then this is a verification error and |
duke@435 | 765 | // it's impossible to interpret the code. Simultaneously monitor |
duke@435 | 766 | // states are being check to see if they nest statically. If monitor |
duke@435 | 767 | // depths match up then their states are merged. Otherwise the |
duke@435 | 768 | // mismatch is simply recorded and interpretation continues since |
duke@435 | 769 | // monitor matching is purely informational and doesn't say anything |
duke@435 | 770 | // about the correctness of the code. |
duke@435 | 771 | void GenerateOopMap::merge_state_into_bb(BasicBlock *bb) { |
duke@435 | 772 | assert(bb->is_alive(), "merging state into a dead basicblock"); |
duke@435 | 773 | |
duke@435 | 774 | if (_stack_top == bb->_stack_top) { |
duke@435 | 775 | // always merge local state even if monitors don't match. |
duke@435 | 776 | if (merge_local_state_vectors(_state, bb->_state)) { |
duke@435 | 777 | bb->set_changed(true); |
duke@435 | 778 | } |
duke@435 | 779 | if (_monitor_top == bb->_monitor_top) { |
duke@435 | 780 | // monitors still match so continue merging monitor states. |
duke@435 | 781 | if (merge_monitor_state_vectors(_state, bb->_state)) { |
duke@435 | 782 | bb->set_changed(true); |
duke@435 | 783 | } |
duke@435 | 784 | } else { |
duke@435 | 785 | if (TraceMonitorMismatch) { |
duke@435 | 786 | report_monitor_mismatch("monitor stack height merge conflict"); |
duke@435 | 787 | } |
duke@435 | 788 | // When the monitor stacks are not matched, we set _monitor_top to |
duke@435 | 789 | // bad_monitors. This signals that, from here on, the monitor stack cannot |
duke@435 | 790 | // be trusted. In particular, monitorexit bytecodes may throw |
duke@435 | 791 | // exceptions. We mark this block as changed so that the change |
duke@435 | 792 | // propagates properly. |
duke@435 | 793 | bb->_monitor_top = bad_monitors; |
duke@435 | 794 | bb->set_changed(true); |
duke@435 | 795 | _monitor_safe = false; |
duke@435 | 796 | } |
duke@435 | 797 | } else if (!bb->is_reachable()) { |
duke@435 | 798 | // First time we look at this BB |
duke@435 | 799 | copy_state(bb->_state, _state); |
duke@435 | 800 | bb->_stack_top = _stack_top; |
duke@435 | 801 | bb->_monitor_top = _monitor_top; |
duke@435 | 802 | bb->set_changed(true); |
duke@435 | 803 | } else { |
duke@435 | 804 | verify_error("stack height conflict: %d vs. %d", _stack_top, bb->_stack_top); |
duke@435 | 805 | } |
duke@435 | 806 | } |
duke@435 | 807 | |
duke@435 | 808 | void GenerateOopMap::merge_state(GenerateOopMap *gom, int bci, int* data) { |
duke@435 | 809 | gom->merge_state_into_bb(gom->get_basic_block_at(bci)); |
duke@435 | 810 | } |
duke@435 | 811 | |
duke@435 | 812 | void GenerateOopMap::set_var(int localNo, CellTypeState cts) { |
duke@435 | 813 | assert(cts.is_reference() || cts.is_value() || cts.is_address(), |
duke@435 | 814 | "wrong celltypestate"); |
duke@435 | 815 | if (localNo < 0 || localNo > _max_locals) { |
duke@435 | 816 | verify_error("variable write error: r%d", localNo); |
duke@435 | 817 | return; |
duke@435 | 818 | } |
duke@435 | 819 | vars()[localNo] = cts; |
duke@435 | 820 | } |
duke@435 | 821 | |
duke@435 | 822 | CellTypeState GenerateOopMap::get_var(int localNo) { |
duke@435 | 823 | assert(localNo < _max_locals + _nof_refval_conflicts, "variable read error") |
duke@435 | 824 | if (localNo < 0 || localNo > _max_locals) { |
duke@435 | 825 | verify_error("variable read error: r%d", localNo); |
duke@435 | 826 | return valCTS; // just to pick something; |
duke@435 | 827 | } |
duke@435 | 828 | return vars()[localNo]; |
duke@435 | 829 | } |
duke@435 | 830 | |
duke@435 | 831 | CellTypeState GenerateOopMap::pop() { |
duke@435 | 832 | if ( _stack_top <= 0) { |
duke@435 | 833 | verify_error("stack underflow"); |
duke@435 | 834 | return valCTS; // just to pick something |
duke@435 | 835 | } |
duke@435 | 836 | return stack()[--_stack_top]; |
duke@435 | 837 | } |
duke@435 | 838 | |
duke@435 | 839 | void GenerateOopMap::push(CellTypeState cts) { |
duke@435 | 840 | if ( _stack_top >= _max_stack) { |
duke@435 | 841 | verify_error("stack overflow"); |
duke@435 | 842 | return; |
duke@435 | 843 | } |
duke@435 | 844 | stack()[_stack_top++] = cts; |
duke@435 | 845 | } |
duke@435 | 846 | |
duke@435 | 847 | CellTypeState GenerateOopMap::monitor_pop() { |
duke@435 | 848 | assert(_monitor_top != bad_monitors, "monitor_pop called on error monitor stack"); |
duke@435 | 849 | if (_monitor_top == 0) { |
duke@435 | 850 | // We have detected a pop of an empty monitor stack. |
duke@435 | 851 | _monitor_safe = false; |
duke@435 | 852 | _monitor_top = bad_monitors; |
duke@435 | 853 | |
duke@435 | 854 | if (TraceMonitorMismatch) { |
duke@435 | 855 | report_monitor_mismatch("monitor stack underflow"); |
duke@435 | 856 | } |
duke@435 | 857 | return CellTypeState::ref; // just to keep the analysis going. |
duke@435 | 858 | } |
duke@435 | 859 | return monitors()[--_monitor_top]; |
duke@435 | 860 | } |
duke@435 | 861 | |
duke@435 | 862 | void GenerateOopMap::monitor_push(CellTypeState cts) { |
duke@435 | 863 | assert(_monitor_top != bad_monitors, "monitor_push called on error monitor stack"); |
duke@435 | 864 | if (_monitor_top >= _max_monitors) { |
duke@435 | 865 | // Some monitorenter is being executed more than once. |
duke@435 | 866 | // This means that the monitor stack cannot be simulated. |
duke@435 | 867 | _monitor_safe = false; |
duke@435 | 868 | _monitor_top = bad_monitors; |
duke@435 | 869 | |
duke@435 | 870 | if (TraceMonitorMismatch) { |
duke@435 | 871 | report_monitor_mismatch("monitor stack overflow"); |
duke@435 | 872 | } |
duke@435 | 873 | return; |
duke@435 | 874 | } |
duke@435 | 875 | monitors()[_monitor_top++] = cts; |
duke@435 | 876 | } |
duke@435 | 877 | |
duke@435 | 878 | // |
duke@435 | 879 | // Interpretation handling methods |
duke@435 | 880 | // |
duke@435 | 881 | |
duke@435 | 882 | void GenerateOopMap::do_interpretation() |
duke@435 | 883 | { |
duke@435 | 884 | // "i" is just for debugging, so we can detect cases where this loop is |
duke@435 | 885 | // iterated more than once. |
duke@435 | 886 | int i = 0; |
duke@435 | 887 | do { |
duke@435 | 888 | #ifndef PRODUCT |
duke@435 | 889 | if (TraceNewOopMapGeneration) { |
duke@435 | 890 | tty->print("\n\nIteration #%d of do_interpretation loop, method:\n", i); |
duke@435 | 891 | method()->print_name(tty); |
duke@435 | 892 | tty->print("\n\n"); |
duke@435 | 893 | } |
duke@435 | 894 | #endif |
duke@435 | 895 | _conflict = false; |
duke@435 | 896 | _monitor_safe = true; |
duke@435 | 897 | // init_state is now called from init_basic_blocks. The length of a |
duke@435 | 898 | // state vector cannot be determined until we have made a pass through |
duke@435 | 899 | // the bytecodes counting the possible monitor entries. |
duke@435 | 900 | if (!_got_error) init_basic_blocks(); |
duke@435 | 901 | if (!_got_error) setup_method_entry_state(); |
duke@435 | 902 | if (!_got_error) interp_all(); |
duke@435 | 903 | if (!_got_error) rewrite_refval_conflicts(); |
duke@435 | 904 | i++; |
duke@435 | 905 | } while (_conflict && !_got_error); |
duke@435 | 906 | } |
duke@435 | 907 | |
duke@435 | 908 | void GenerateOopMap::init_basic_blocks() { |
duke@435 | 909 | // Note: Could consider reserving only the needed space for each BB's state |
duke@435 | 910 | // (entry stack may not be of maximal height for every basic block). |
duke@435 | 911 | // But cumbersome since we don't know the stack heights yet. (Nor the |
duke@435 | 912 | // monitor stack heights...) |
duke@435 | 913 | |
duke@435 | 914 | _basic_blocks = NEW_RESOURCE_ARRAY(BasicBlock, _bb_count); |
duke@435 | 915 | |
duke@435 | 916 | // Make a pass through the bytecodes. Count the number of monitorenters. |
duke@435 | 917 | // This can be used an upper bound on the monitor stack depth in programs |
duke@435 | 918 | // which obey stack discipline with their monitor usage. Initialize the |
duke@435 | 919 | // known information about basic blocks. |
duke@435 | 920 | BytecodeStream j(_method); |
duke@435 | 921 | Bytecodes::Code bytecode; |
duke@435 | 922 | |
duke@435 | 923 | int bbNo = 0; |
duke@435 | 924 | int monitor_count = 0; |
duke@435 | 925 | int prev_bci = -1; |
duke@435 | 926 | while( (bytecode = j.next()) >= 0) { |
duke@435 | 927 | if (j.code() == Bytecodes::_monitorenter) { |
duke@435 | 928 | monitor_count++; |
duke@435 | 929 | } |
duke@435 | 930 | |
duke@435 | 931 | int bci = j.bci(); |
duke@435 | 932 | if (is_bb_header(bci)) { |
duke@435 | 933 | // Initialize the basicblock structure |
duke@435 | 934 | BasicBlock *bb = _basic_blocks + bbNo; |
duke@435 | 935 | bb->_bci = bci; |
duke@435 | 936 | bb->_max_locals = _max_locals; |
duke@435 | 937 | bb->_max_stack = _max_stack; |
duke@435 | 938 | bb->set_changed(false); |
duke@435 | 939 | bb->_stack_top = BasicBlock::_dead_basic_block; // Initialize all basicblocks are dead. |
duke@435 | 940 | bb->_monitor_top = bad_monitors; |
duke@435 | 941 | |
duke@435 | 942 | if (bbNo > 0) { |
duke@435 | 943 | _basic_blocks[bbNo - 1]._end_bci = prev_bci; |
duke@435 | 944 | } |
duke@435 | 945 | |
duke@435 | 946 | bbNo++; |
duke@435 | 947 | } |
duke@435 | 948 | // Remember prevous bci. |
duke@435 | 949 | prev_bci = bci; |
duke@435 | 950 | } |
duke@435 | 951 | // Set |
duke@435 | 952 | _basic_blocks[bbNo-1]._end_bci = prev_bci; |
duke@435 | 953 | |
duke@435 | 954 | |
duke@435 | 955 | _max_monitors = monitor_count; |
duke@435 | 956 | |
duke@435 | 957 | // Now that we have a bound on the depth of the monitor stack, we can |
duke@435 | 958 | // initialize the CellTypeState-related information. |
duke@435 | 959 | init_state(); |
duke@435 | 960 | |
duke@435 | 961 | // We allocate space for all state-vectors for all basicblocks in one huge chuck. |
duke@435 | 962 | // Then in the next part of the code, we set a pointer in each _basic_block that |
duke@435 | 963 | // points to each piece. |
duke@435 | 964 | CellTypeState *basicBlockState = NEW_RESOURCE_ARRAY(CellTypeState, bbNo * _state_len); |
duke@435 | 965 | memset(basicBlockState, 0, bbNo * _state_len * sizeof(CellTypeState)); |
duke@435 | 966 | |
duke@435 | 967 | // Make a pass over the basicblocks and assign their state vectors. |
duke@435 | 968 | for (int blockNum=0; blockNum < bbNo; blockNum++) { |
duke@435 | 969 | BasicBlock *bb = _basic_blocks + blockNum; |
duke@435 | 970 | bb->_state = basicBlockState + blockNum * _state_len; |
duke@435 | 971 | |
duke@435 | 972 | #ifdef ASSERT |
duke@435 | 973 | if (blockNum + 1 < bbNo) { |
duke@435 | 974 | address bcp = _method->bcp_from(bb->_end_bci); |
duke@435 | 975 | int bc_len = Bytecodes::java_length_at(bcp); |
duke@435 | 976 | assert(bb->_end_bci + bc_len == bb[1]._bci, "unmatched bci info in basicblock"); |
duke@435 | 977 | } |
duke@435 | 978 | #endif |
duke@435 | 979 | } |
duke@435 | 980 | #ifdef ASSERT |
duke@435 | 981 | { BasicBlock *bb = &_basic_blocks[bbNo-1]; |
duke@435 | 982 | address bcp = _method->bcp_from(bb->_end_bci); |
duke@435 | 983 | int bc_len = Bytecodes::java_length_at(bcp); |
duke@435 | 984 | assert(bb->_end_bci + bc_len == _method->code_size(), "wrong end bci"); |
duke@435 | 985 | } |
duke@435 | 986 | #endif |
duke@435 | 987 | |
duke@435 | 988 | // Check that the correct number of basicblocks was found |
duke@435 | 989 | if (bbNo !=_bb_count) { |
duke@435 | 990 | if (bbNo < _bb_count) { |
duke@435 | 991 | verify_error("jump into the middle of instruction?"); |
duke@435 | 992 | return; |
duke@435 | 993 | } else { |
duke@435 | 994 | verify_error("extra basic blocks - should not happen?"); |
duke@435 | 995 | return; |
duke@435 | 996 | } |
duke@435 | 997 | } |
duke@435 | 998 | |
duke@435 | 999 | // Mark all alive blocks |
duke@435 | 1000 | mark_reachable_code(); |
duke@435 | 1001 | } |
duke@435 | 1002 | |
duke@435 | 1003 | void GenerateOopMap::setup_method_entry_state() { |
duke@435 | 1004 | |
duke@435 | 1005 | // Initialize all locals to 'uninit' and set stack-height to 0 |
duke@435 | 1006 | make_context_uninitialized(); |
duke@435 | 1007 | |
duke@435 | 1008 | // Initialize CellState type of arguments |
duke@435 | 1009 | methodsig_to_effect(method()->signature(), method()->is_static(), vars()); |
duke@435 | 1010 | |
duke@435 | 1011 | // If some references must be pre-assigned to null, then set that up |
duke@435 | 1012 | initialize_vars(); |
duke@435 | 1013 | |
duke@435 | 1014 | // This is the start state |
duke@435 | 1015 | merge_state_into_bb(&_basic_blocks[0]); |
duke@435 | 1016 | |
duke@435 | 1017 | assert(_basic_blocks[0].changed(), "we are not getting off the ground"); |
duke@435 | 1018 | } |
duke@435 | 1019 | |
duke@435 | 1020 | // The instruction at bci is changing size by "delta". Update the basic blocks. |
duke@435 | 1021 | void GenerateOopMap::update_basic_blocks(int bci, int delta, |
duke@435 | 1022 | int new_method_size) { |
duke@435 | 1023 | assert(new_method_size >= method()->code_size() + delta, |
duke@435 | 1024 | "new method size is too small"); |
duke@435 | 1025 | int newWords = binsToHold(new_method_size); |
duke@435 | 1026 | |
duke@435 | 1027 | uintptr_t * new_bb_hdr_bits = NEW_RESOURCE_ARRAY(uintptr_t, newWords); |
duke@435 | 1028 | |
duke@435 | 1029 | BitMap bb_bits(new_bb_hdr_bits, new_method_size); |
duke@435 | 1030 | bb_bits.clear(); |
duke@435 | 1031 | |
duke@435 | 1032 | for(int k = 0; k < _bb_count; k++) { |
duke@435 | 1033 | if (_basic_blocks[k]._bci > bci) { |
duke@435 | 1034 | _basic_blocks[k]._bci += delta; |
duke@435 | 1035 | _basic_blocks[k]._end_bci += delta; |
duke@435 | 1036 | } |
duke@435 | 1037 | bb_bits.at_put(_basic_blocks[k]._bci, true); |
duke@435 | 1038 | } |
duke@435 | 1039 | _bb_hdr_bits = new_bb_hdr_bits ; |
duke@435 | 1040 | } |
duke@435 | 1041 | |
duke@435 | 1042 | // |
duke@435 | 1043 | // Initvars handling |
duke@435 | 1044 | // |
duke@435 | 1045 | |
duke@435 | 1046 | void GenerateOopMap::initialize_vars() { |
duke@435 | 1047 | for (int k = 0; k < _init_vars->length(); k++) |
duke@435 | 1048 | _state[_init_vars->at(k)] = CellTypeState::make_slot_ref(k); |
duke@435 | 1049 | } |
duke@435 | 1050 | |
duke@435 | 1051 | void GenerateOopMap::add_to_ref_init_set(int localNo) { |
duke@435 | 1052 | |
duke@435 | 1053 | if (TraceNewOopMapGeneration) |
duke@435 | 1054 | tty->print_cr("Added init vars: %d", localNo); |
duke@435 | 1055 | |
duke@435 | 1056 | // Is it already in the set? |
duke@435 | 1057 | if (_init_vars->contains(localNo) ) |
duke@435 | 1058 | return; |
duke@435 | 1059 | |
duke@435 | 1060 | _init_vars->append(localNo); |
duke@435 | 1061 | } |
duke@435 | 1062 | |
duke@435 | 1063 | // |
duke@435 | 1064 | // Interpreration code |
duke@435 | 1065 | // |
duke@435 | 1066 | |
duke@435 | 1067 | void GenerateOopMap::interp_all() { |
duke@435 | 1068 | bool change = true; |
duke@435 | 1069 | |
duke@435 | 1070 | while (change && !_got_error) { |
duke@435 | 1071 | change = false; |
duke@435 | 1072 | for (int i = 0; i < _bb_count && !_got_error; i++) { |
duke@435 | 1073 | BasicBlock *bb = &_basic_blocks[i]; |
duke@435 | 1074 | if (bb->changed()) { |
duke@435 | 1075 | if (_got_error) return; |
duke@435 | 1076 | change = true; |
duke@435 | 1077 | bb->set_changed(false); |
duke@435 | 1078 | interp_bb(bb); |
duke@435 | 1079 | } |
duke@435 | 1080 | } |
duke@435 | 1081 | } |
duke@435 | 1082 | } |
duke@435 | 1083 | |
duke@435 | 1084 | void GenerateOopMap::interp_bb(BasicBlock *bb) { |
duke@435 | 1085 | |
duke@435 | 1086 | // We do not want to do anything in case the basic-block has not been initialized. This |
duke@435 | 1087 | // will happen in the case where there is dead-code hang around in a method. |
duke@435 | 1088 | assert(bb->is_reachable(), "should be reachable or deadcode exist"); |
duke@435 | 1089 | restore_state(bb); |
duke@435 | 1090 | |
duke@435 | 1091 | BytecodeStream itr(_method); |
duke@435 | 1092 | |
duke@435 | 1093 | // Set iterator interval to be the current basicblock |
duke@435 | 1094 | int lim_bci = next_bb_start_pc(bb); |
duke@435 | 1095 | itr.set_interval(bb->_bci, lim_bci); |
duke@435 | 1096 | assert(lim_bci != bb->_bci, "must be at least one instruction in a basicblock"); |
duke@435 | 1097 | itr.next(); // read first instruction |
duke@435 | 1098 | |
duke@435 | 1099 | // Iterates through all bytecodes except the last in a basic block. |
duke@435 | 1100 | // We handle the last one special, since there is controlflow change. |
duke@435 | 1101 | while(itr.next_bci() < lim_bci && !_got_error) { |
duke@435 | 1102 | if (_has_exceptions || _monitor_top != 0) { |
duke@435 | 1103 | // We do not need to interpret the results of exceptional |
duke@435 | 1104 | // continuation from this instruction when the method has no |
duke@435 | 1105 | // exception handlers and the monitor stack is currently |
duke@435 | 1106 | // empty. |
duke@435 | 1107 | do_exception_edge(&itr); |
duke@435 | 1108 | } |
duke@435 | 1109 | interp1(&itr); |
duke@435 | 1110 | itr.next(); |
duke@435 | 1111 | } |
duke@435 | 1112 | |
duke@435 | 1113 | // Handle last instruction. |
duke@435 | 1114 | if (!_got_error) { |
duke@435 | 1115 | assert(itr.next_bci() == lim_bci, "must point to end"); |
duke@435 | 1116 | if (_has_exceptions || _monitor_top != 0) { |
duke@435 | 1117 | do_exception_edge(&itr); |
duke@435 | 1118 | } |
duke@435 | 1119 | interp1(&itr); |
duke@435 | 1120 | |
duke@435 | 1121 | bool fall_through = jump_targets_do(&itr, GenerateOopMap::merge_state, NULL); |
duke@435 | 1122 | if (_got_error) return; |
duke@435 | 1123 | |
duke@435 | 1124 | if (itr.code() == Bytecodes::_ret) { |
duke@435 | 1125 | assert(!fall_through, "cannot be set if ret instruction"); |
duke@435 | 1126 | // Automatically handles 'wide' ret indicies |
duke@435 | 1127 | ret_jump_targets_do(&itr, GenerateOopMap::merge_state, itr.get_index(), NULL); |
duke@435 | 1128 | } else if (fall_through) { |
duke@435 | 1129 | // Hit end of BB, but the instr. was a fall-through instruction, |
duke@435 | 1130 | // so perform transition as if the BB ended in a "jump". |
duke@435 | 1131 | if (lim_bci != bb[1]._bci) { |
duke@435 | 1132 | verify_error("bytecodes fell through last instruction"); |
duke@435 | 1133 | return; |
duke@435 | 1134 | } |
duke@435 | 1135 | merge_state_into_bb(bb + 1); |
duke@435 | 1136 | } |
duke@435 | 1137 | } |
duke@435 | 1138 | } |
duke@435 | 1139 | |
duke@435 | 1140 | void GenerateOopMap::do_exception_edge(BytecodeStream* itr) { |
duke@435 | 1141 | // Only check exception edge, if bytecode can trap |
duke@435 | 1142 | if (!Bytecodes::can_trap(itr->code())) return; |
duke@435 | 1143 | switch (itr->code()) { |
duke@435 | 1144 | case Bytecodes::_aload_0: |
duke@435 | 1145 | // These bytecodes can trap for rewriting. We need to assume that |
duke@435 | 1146 | // they do not throw exceptions to make the monitor analysis work. |
duke@435 | 1147 | return; |
duke@435 | 1148 | |
duke@435 | 1149 | case Bytecodes::_ireturn: |
duke@435 | 1150 | case Bytecodes::_lreturn: |
duke@435 | 1151 | case Bytecodes::_freturn: |
duke@435 | 1152 | case Bytecodes::_dreturn: |
duke@435 | 1153 | case Bytecodes::_areturn: |
duke@435 | 1154 | case Bytecodes::_return: |
duke@435 | 1155 | // If the monitor stack height is not zero when we leave the method, |
duke@435 | 1156 | // then we are either exiting with a non-empty stack or we have |
duke@435 | 1157 | // found monitor trouble earlier in our analysis. In either case, |
duke@435 | 1158 | // assume an exception could be taken here. |
duke@435 | 1159 | if (_monitor_top == 0) { |
duke@435 | 1160 | return; |
duke@435 | 1161 | } |
duke@435 | 1162 | break; |
duke@435 | 1163 | |
duke@435 | 1164 | case Bytecodes::_monitorexit: |
duke@435 | 1165 | // If the monitor stack height is bad_monitors, then we have detected a |
duke@435 | 1166 | // monitor matching problem earlier in the analysis. If the |
duke@435 | 1167 | // monitor stack height is 0, we are about to pop a monitor |
duke@435 | 1168 | // off of an empty stack. In either case, the bytecode |
duke@435 | 1169 | // could throw an exception. |
duke@435 | 1170 | if (_monitor_top != bad_monitors && _monitor_top != 0) { |
duke@435 | 1171 | return; |
duke@435 | 1172 | } |
duke@435 | 1173 | break; |
duke@435 | 1174 | } |
duke@435 | 1175 | |
duke@435 | 1176 | if (_has_exceptions) { |
duke@435 | 1177 | int bci = itr->bci(); |
duke@435 | 1178 | typeArrayOop exct = method()->exception_table(); |
duke@435 | 1179 | for(int i = 0; i< exct->length(); i+=4) { |
duke@435 | 1180 | int start_pc = exct->int_at(i); |
duke@435 | 1181 | int end_pc = exct->int_at(i+1); |
duke@435 | 1182 | int handler_pc = exct->int_at(i+2); |
duke@435 | 1183 | int catch_type = exct->int_at(i+3); |
duke@435 | 1184 | |
duke@435 | 1185 | if (start_pc <= bci && bci < end_pc) { |
duke@435 | 1186 | BasicBlock *excBB = get_basic_block_at(handler_pc); |
duke@435 | 1187 | CellTypeState *excStk = excBB->stack(); |
duke@435 | 1188 | CellTypeState *cOpStck = stack(); |
duke@435 | 1189 | CellTypeState cOpStck_0 = cOpStck[0]; |
duke@435 | 1190 | int cOpStackTop = _stack_top; |
duke@435 | 1191 | |
duke@435 | 1192 | // Exception stacks are always the same. |
duke@435 | 1193 | assert(method()->max_stack() > 0, "sanity check"); |
duke@435 | 1194 | |
duke@435 | 1195 | // We remembered the size and first element of "cOpStck" |
duke@435 | 1196 | // above; now we temporarily set them to the appropriate |
duke@435 | 1197 | // values for an exception handler. */ |
duke@435 | 1198 | cOpStck[0] = CellTypeState::make_slot_ref(_max_locals); |
duke@435 | 1199 | _stack_top = 1; |
duke@435 | 1200 | |
duke@435 | 1201 | merge_state_into_bb(excBB); |
duke@435 | 1202 | |
duke@435 | 1203 | // Now undo the temporary change. |
duke@435 | 1204 | cOpStck[0] = cOpStck_0; |
duke@435 | 1205 | _stack_top = cOpStackTop; |
duke@435 | 1206 | |
duke@435 | 1207 | // If this is a "catch all" handler, then we do not need to |
duke@435 | 1208 | // consider any additional handlers. |
duke@435 | 1209 | if (catch_type == 0) { |
duke@435 | 1210 | return; |
duke@435 | 1211 | } |
duke@435 | 1212 | } |
duke@435 | 1213 | } |
duke@435 | 1214 | } |
duke@435 | 1215 | |
duke@435 | 1216 | // It is possible that none of the exception handlers would have caught |
duke@435 | 1217 | // the exception. In this case, we will exit the method. We must |
duke@435 | 1218 | // ensure that the monitor stack is empty in this case. |
duke@435 | 1219 | if (_monitor_top == 0) { |
duke@435 | 1220 | return; |
duke@435 | 1221 | } |
duke@435 | 1222 | |
duke@435 | 1223 | // We pessimistically assume that this exception can escape the |
duke@435 | 1224 | // method. (It is possible that it will always be caught, but |
duke@435 | 1225 | // we don't care to analyse the types of the catch clauses.) |
duke@435 | 1226 | |
duke@435 | 1227 | // We don't set _monitor_top to bad_monitors because there are no successors |
duke@435 | 1228 | // to this exceptional exit. |
duke@435 | 1229 | |
duke@435 | 1230 | if (TraceMonitorMismatch && _monitor_safe) { |
duke@435 | 1231 | // We check _monitor_safe so that we only report the first mismatched |
duke@435 | 1232 | // exceptional exit. |
duke@435 | 1233 | report_monitor_mismatch("non-empty monitor stack at exceptional exit"); |
duke@435 | 1234 | } |
duke@435 | 1235 | _monitor_safe = false; |
duke@435 | 1236 | |
duke@435 | 1237 | } |
duke@435 | 1238 | |
duke@435 | 1239 | void GenerateOopMap::report_monitor_mismatch(const char *msg) { |
duke@435 | 1240 | #ifndef PRODUCT |
duke@435 | 1241 | tty->print(" Monitor mismatch in method "); |
duke@435 | 1242 | method()->print_short_name(tty); |
duke@435 | 1243 | tty->print_cr(": %s", msg); |
duke@435 | 1244 | #endif |
duke@435 | 1245 | } |
duke@435 | 1246 | |
duke@435 | 1247 | void GenerateOopMap::print_states(outputStream *os, |
duke@435 | 1248 | CellTypeState* vec, int num) { |
duke@435 | 1249 | for (int i = 0; i < num; i++) { |
duke@435 | 1250 | vec[i].print(tty); |
duke@435 | 1251 | } |
duke@435 | 1252 | } |
duke@435 | 1253 | |
duke@435 | 1254 | // Print the state values at the current bytecode. |
duke@435 | 1255 | void GenerateOopMap::print_current_state(outputStream *os, |
duke@435 | 1256 | BytecodeStream *currentBC, |
duke@435 | 1257 | bool detailed) { |
duke@435 | 1258 | |
duke@435 | 1259 | if (detailed) { |
duke@435 | 1260 | os->print(" %4d vars = ", currentBC->bci()); |
duke@435 | 1261 | print_states(os, vars(), _max_locals); |
duke@435 | 1262 | os->print(" %s", Bytecodes::name(currentBC->code())); |
duke@435 | 1263 | switch(currentBC->code()) { |
duke@435 | 1264 | case Bytecodes::_invokevirtual: |
duke@435 | 1265 | case Bytecodes::_invokespecial: |
duke@435 | 1266 | case Bytecodes::_invokestatic: |
duke@435 | 1267 | case Bytecodes::_invokeinterface: |
duke@435 | 1268 | int idx = currentBC->get_index_big(); |
duke@435 | 1269 | constantPoolOop cp = method()->constants(); |
duke@435 | 1270 | int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); |
duke@435 | 1271 | int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); |
duke@435 | 1272 | symbolOop signature = cp->symbol_at(signatureIdx); |
duke@435 | 1273 | os->print("%s", signature->as_C_string()); |
duke@435 | 1274 | } |
duke@435 | 1275 | os->cr(); |
duke@435 | 1276 | os->print(" stack = "); |
duke@435 | 1277 | print_states(os, stack(), _stack_top); |
duke@435 | 1278 | os->cr(); |
duke@435 | 1279 | if (_monitor_top != bad_monitors) { |
duke@435 | 1280 | os->print(" monitors = "); |
duke@435 | 1281 | print_states(os, monitors(), _monitor_top); |
duke@435 | 1282 | } else { |
duke@435 | 1283 | os->print(" [bad monitor stack]"); |
duke@435 | 1284 | } |
duke@435 | 1285 | os->cr(); |
duke@435 | 1286 | } else { |
duke@435 | 1287 | os->print(" %4d vars = '%s' ", currentBC->bci(), state_vec_to_string(vars(), _max_locals)); |
duke@435 | 1288 | os->print(" stack = '%s' ", state_vec_to_string(stack(), _stack_top)); |
duke@435 | 1289 | if (_monitor_top != bad_monitors) { |
duke@435 | 1290 | os->print(" monitors = '%s' \t%s", state_vec_to_string(monitors(), _monitor_top), Bytecodes::name(currentBC->code())); |
duke@435 | 1291 | } else { |
duke@435 | 1292 | os->print(" [bad monitor stack]"); |
duke@435 | 1293 | } |
duke@435 | 1294 | switch(currentBC->code()) { |
duke@435 | 1295 | case Bytecodes::_invokevirtual: |
duke@435 | 1296 | case Bytecodes::_invokespecial: |
duke@435 | 1297 | case Bytecodes::_invokestatic: |
duke@435 | 1298 | case Bytecodes::_invokeinterface: |
duke@435 | 1299 | int idx = currentBC->get_index_big(); |
duke@435 | 1300 | constantPoolOop cp = method()->constants(); |
duke@435 | 1301 | int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); |
duke@435 | 1302 | int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); |
duke@435 | 1303 | symbolOop signature = cp->symbol_at(signatureIdx); |
duke@435 | 1304 | os->print("%s", signature->as_C_string()); |
duke@435 | 1305 | } |
duke@435 | 1306 | os->cr(); |
duke@435 | 1307 | } |
duke@435 | 1308 | } |
duke@435 | 1309 | |
duke@435 | 1310 | // Sets the current state to be the state after executing the |
duke@435 | 1311 | // current instruction, starting in the current state. |
duke@435 | 1312 | void GenerateOopMap::interp1(BytecodeStream *itr) { |
duke@435 | 1313 | if (TraceNewOopMapGeneration) { |
duke@435 | 1314 | print_current_state(tty, itr, TraceNewOopMapGenerationDetailed); |
duke@435 | 1315 | } |
duke@435 | 1316 | |
duke@435 | 1317 | // Should we report the results? Result is reported *before* the instruction at the current bci is executed. |
duke@435 | 1318 | // However, not for calls. For calls we do not want to include the arguments, so we postpone the reporting until |
duke@435 | 1319 | // they have been popped (in method ppl). |
duke@435 | 1320 | if (_report_result == true) { |
duke@435 | 1321 | switch(itr->code()) { |
duke@435 | 1322 | case Bytecodes::_invokevirtual: |
duke@435 | 1323 | case Bytecodes::_invokespecial: |
duke@435 | 1324 | case Bytecodes::_invokestatic: |
duke@435 | 1325 | case Bytecodes::_invokeinterface: |
duke@435 | 1326 | _itr_send = itr; |
duke@435 | 1327 | _report_result_for_send = true; |
duke@435 | 1328 | break; |
duke@435 | 1329 | default: |
duke@435 | 1330 | fill_stackmap_for_opcodes(itr, vars(), stack(), _stack_top); |
duke@435 | 1331 | break; |
duke@435 | 1332 | } |
duke@435 | 1333 | } |
duke@435 | 1334 | |
duke@435 | 1335 | // abstract interpretation of current opcode |
duke@435 | 1336 | switch(itr->code()) { |
duke@435 | 1337 | case Bytecodes::_nop: break; |
duke@435 | 1338 | case Bytecodes::_goto: break; |
duke@435 | 1339 | case Bytecodes::_goto_w: break; |
duke@435 | 1340 | case Bytecodes::_iinc: break; |
duke@435 | 1341 | case Bytecodes::_return: do_return_monitor_check(); |
duke@435 | 1342 | break; |
duke@435 | 1343 | |
duke@435 | 1344 | case Bytecodes::_aconst_null: |
duke@435 | 1345 | case Bytecodes::_new: ppush1(CellTypeState::make_line_ref(itr->bci())); |
duke@435 | 1346 | break; |
duke@435 | 1347 | |
duke@435 | 1348 | case Bytecodes::_iconst_m1: |
duke@435 | 1349 | case Bytecodes::_iconst_0: |
duke@435 | 1350 | case Bytecodes::_iconst_1: |
duke@435 | 1351 | case Bytecodes::_iconst_2: |
duke@435 | 1352 | case Bytecodes::_iconst_3: |
duke@435 | 1353 | case Bytecodes::_iconst_4: |
duke@435 | 1354 | case Bytecodes::_iconst_5: |
duke@435 | 1355 | case Bytecodes::_fconst_0: |
duke@435 | 1356 | case Bytecodes::_fconst_1: |
duke@435 | 1357 | case Bytecodes::_fconst_2: |
duke@435 | 1358 | case Bytecodes::_bipush: |
duke@435 | 1359 | case Bytecodes::_sipush: ppush1(valCTS); break; |
duke@435 | 1360 | |
duke@435 | 1361 | case Bytecodes::_lconst_0: |
duke@435 | 1362 | case Bytecodes::_lconst_1: |
duke@435 | 1363 | case Bytecodes::_dconst_0: |
duke@435 | 1364 | case Bytecodes::_dconst_1: ppush(vvCTS); break; |
duke@435 | 1365 | |
duke@435 | 1366 | case Bytecodes::_ldc2_w: ppush(vvCTS); break; |
duke@435 | 1367 | |
duke@435 | 1368 | case Bytecodes::_ldc: do_ldc(itr->get_index(), itr->bci()); break; |
duke@435 | 1369 | case Bytecodes::_ldc_w: do_ldc(itr->get_index_big(), itr->bci());break; |
duke@435 | 1370 | |
duke@435 | 1371 | case Bytecodes::_iload: |
duke@435 | 1372 | case Bytecodes::_fload: ppload(vCTS, itr->get_index()); break; |
duke@435 | 1373 | |
duke@435 | 1374 | case Bytecodes::_lload: |
duke@435 | 1375 | case Bytecodes::_dload: ppload(vvCTS,itr->get_index()); break; |
duke@435 | 1376 | |
duke@435 | 1377 | case Bytecodes::_aload: ppload(rCTS, itr->get_index()); break; |
duke@435 | 1378 | |
duke@435 | 1379 | case Bytecodes::_iload_0: |
duke@435 | 1380 | case Bytecodes::_fload_0: ppload(vCTS, 0); break; |
duke@435 | 1381 | case Bytecodes::_iload_1: |
duke@435 | 1382 | case Bytecodes::_fload_1: ppload(vCTS, 1); break; |
duke@435 | 1383 | case Bytecodes::_iload_2: |
duke@435 | 1384 | case Bytecodes::_fload_2: ppload(vCTS, 2); break; |
duke@435 | 1385 | case Bytecodes::_iload_3: |
duke@435 | 1386 | case Bytecodes::_fload_3: ppload(vCTS, 3); break; |
duke@435 | 1387 | |
duke@435 | 1388 | case Bytecodes::_lload_0: |
duke@435 | 1389 | case Bytecodes::_dload_0: ppload(vvCTS, 0); break; |
duke@435 | 1390 | case Bytecodes::_lload_1: |
duke@435 | 1391 | case Bytecodes::_dload_1: ppload(vvCTS, 1); break; |
duke@435 | 1392 | case Bytecodes::_lload_2: |
duke@435 | 1393 | case Bytecodes::_dload_2: ppload(vvCTS, 2); break; |
duke@435 | 1394 | case Bytecodes::_lload_3: |
duke@435 | 1395 | case Bytecodes::_dload_3: ppload(vvCTS, 3); break; |
duke@435 | 1396 | |
duke@435 | 1397 | case Bytecodes::_aload_0: ppload(rCTS, 0); break; |
duke@435 | 1398 | case Bytecodes::_aload_1: ppload(rCTS, 1); break; |
duke@435 | 1399 | case Bytecodes::_aload_2: ppload(rCTS, 2); break; |
duke@435 | 1400 | case Bytecodes::_aload_3: ppload(rCTS, 3); break; |
duke@435 | 1401 | |
duke@435 | 1402 | case Bytecodes::_iaload: |
duke@435 | 1403 | case Bytecodes::_faload: |
duke@435 | 1404 | case Bytecodes::_baload: |
duke@435 | 1405 | case Bytecodes::_caload: |
duke@435 | 1406 | case Bytecodes::_saload: pp(vrCTS, vCTS); break; |
duke@435 | 1407 | |
duke@435 | 1408 | case Bytecodes::_laload: pp(vrCTS, vvCTS); break; |
duke@435 | 1409 | case Bytecodes::_daload: pp(vrCTS, vvCTS); break; |
duke@435 | 1410 | |
duke@435 | 1411 | case Bytecodes::_aaload: pp_new_ref(vrCTS, itr->bci()); break; |
duke@435 | 1412 | |
duke@435 | 1413 | case Bytecodes::_istore: |
duke@435 | 1414 | case Bytecodes::_fstore: ppstore(vCTS, itr->get_index()); break; |
duke@435 | 1415 | |
duke@435 | 1416 | case Bytecodes::_lstore: |
duke@435 | 1417 | case Bytecodes::_dstore: ppstore(vvCTS, itr->get_index()); break; |
duke@435 | 1418 | |
duke@435 | 1419 | case Bytecodes::_astore: do_astore(itr->get_index()); break; |
duke@435 | 1420 | |
duke@435 | 1421 | case Bytecodes::_istore_0: |
duke@435 | 1422 | case Bytecodes::_fstore_0: ppstore(vCTS, 0); break; |
duke@435 | 1423 | case Bytecodes::_istore_1: |
duke@435 | 1424 | case Bytecodes::_fstore_1: ppstore(vCTS, 1); break; |
duke@435 | 1425 | case Bytecodes::_istore_2: |
duke@435 | 1426 | case Bytecodes::_fstore_2: ppstore(vCTS, 2); break; |
duke@435 | 1427 | case Bytecodes::_istore_3: |
duke@435 | 1428 | case Bytecodes::_fstore_3: ppstore(vCTS, 3); break; |
duke@435 | 1429 | |
duke@435 | 1430 | case Bytecodes::_lstore_0: |
duke@435 | 1431 | case Bytecodes::_dstore_0: ppstore(vvCTS, 0); break; |
duke@435 | 1432 | case Bytecodes::_lstore_1: |
duke@435 | 1433 | case Bytecodes::_dstore_1: ppstore(vvCTS, 1); break; |
duke@435 | 1434 | case Bytecodes::_lstore_2: |
duke@435 | 1435 | case Bytecodes::_dstore_2: ppstore(vvCTS, 2); break; |
duke@435 | 1436 | case Bytecodes::_lstore_3: |
duke@435 | 1437 | case Bytecodes::_dstore_3: ppstore(vvCTS, 3); break; |
duke@435 | 1438 | |
duke@435 | 1439 | case Bytecodes::_astore_0: do_astore(0); break; |
duke@435 | 1440 | case Bytecodes::_astore_1: do_astore(1); break; |
duke@435 | 1441 | case Bytecodes::_astore_2: do_astore(2); break; |
duke@435 | 1442 | case Bytecodes::_astore_3: do_astore(3); break; |
duke@435 | 1443 | |
duke@435 | 1444 | case Bytecodes::_iastore: |
duke@435 | 1445 | case Bytecodes::_fastore: |
duke@435 | 1446 | case Bytecodes::_bastore: |
duke@435 | 1447 | case Bytecodes::_castore: |
duke@435 | 1448 | case Bytecodes::_sastore: ppop(vvrCTS); break; |
duke@435 | 1449 | case Bytecodes::_lastore: |
duke@435 | 1450 | case Bytecodes::_dastore: ppop(vvvrCTS); break; |
duke@435 | 1451 | case Bytecodes::_aastore: ppop(rvrCTS); break; |
duke@435 | 1452 | |
duke@435 | 1453 | case Bytecodes::_pop: ppop_any(1); break; |
duke@435 | 1454 | case Bytecodes::_pop2: ppop_any(2); break; |
duke@435 | 1455 | |
duke@435 | 1456 | case Bytecodes::_dup: ppdupswap(1, "11"); break; |
duke@435 | 1457 | case Bytecodes::_dup_x1: ppdupswap(2, "121"); break; |
duke@435 | 1458 | case Bytecodes::_dup_x2: ppdupswap(3, "1321"); break; |
duke@435 | 1459 | case Bytecodes::_dup2: ppdupswap(2, "2121"); break; |
duke@435 | 1460 | case Bytecodes::_dup2_x1: ppdupswap(3, "21321"); break; |
duke@435 | 1461 | case Bytecodes::_dup2_x2: ppdupswap(4, "214321"); break; |
duke@435 | 1462 | case Bytecodes::_swap: ppdupswap(2, "12"); break; |
duke@435 | 1463 | |
duke@435 | 1464 | case Bytecodes::_iadd: |
duke@435 | 1465 | case Bytecodes::_fadd: |
duke@435 | 1466 | case Bytecodes::_isub: |
duke@435 | 1467 | case Bytecodes::_fsub: |
duke@435 | 1468 | case Bytecodes::_imul: |
duke@435 | 1469 | case Bytecodes::_fmul: |
duke@435 | 1470 | case Bytecodes::_idiv: |
duke@435 | 1471 | case Bytecodes::_fdiv: |
duke@435 | 1472 | case Bytecodes::_irem: |
duke@435 | 1473 | case Bytecodes::_frem: |
duke@435 | 1474 | case Bytecodes::_ishl: |
duke@435 | 1475 | case Bytecodes::_ishr: |
duke@435 | 1476 | case Bytecodes::_iushr: |
duke@435 | 1477 | case Bytecodes::_iand: |
duke@435 | 1478 | case Bytecodes::_ior: |
duke@435 | 1479 | case Bytecodes::_ixor: |
duke@435 | 1480 | case Bytecodes::_l2f: |
duke@435 | 1481 | case Bytecodes::_l2i: |
duke@435 | 1482 | case Bytecodes::_d2f: |
duke@435 | 1483 | case Bytecodes::_d2i: |
duke@435 | 1484 | case Bytecodes::_fcmpl: |
duke@435 | 1485 | case Bytecodes::_fcmpg: pp(vvCTS, vCTS); break; |
duke@435 | 1486 | |
duke@435 | 1487 | case Bytecodes::_ladd: |
duke@435 | 1488 | case Bytecodes::_dadd: |
duke@435 | 1489 | case Bytecodes::_lsub: |
duke@435 | 1490 | case Bytecodes::_dsub: |
duke@435 | 1491 | case Bytecodes::_lmul: |
duke@435 | 1492 | case Bytecodes::_dmul: |
duke@435 | 1493 | case Bytecodes::_ldiv: |
duke@435 | 1494 | case Bytecodes::_ddiv: |
duke@435 | 1495 | case Bytecodes::_lrem: |
duke@435 | 1496 | case Bytecodes::_drem: |
duke@435 | 1497 | case Bytecodes::_land: |
duke@435 | 1498 | case Bytecodes::_lor: |
duke@435 | 1499 | case Bytecodes::_lxor: pp(vvvvCTS, vvCTS); break; |
duke@435 | 1500 | |
duke@435 | 1501 | case Bytecodes::_ineg: |
duke@435 | 1502 | case Bytecodes::_fneg: |
duke@435 | 1503 | case Bytecodes::_i2f: |
duke@435 | 1504 | case Bytecodes::_f2i: |
duke@435 | 1505 | case Bytecodes::_i2c: |
duke@435 | 1506 | case Bytecodes::_i2s: |
duke@435 | 1507 | case Bytecodes::_i2b: pp(vCTS, vCTS); break; |
duke@435 | 1508 | |
duke@435 | 1509 | case Bytecodes::_lneg: |
duke@435 | 1510 | case Bytecodes::_dneg: |
duke@435 | 1511 | case Bytecodes::_l2d: |
duke@435 | 1512 | case Bytecodes::_d2l: pp(vvCTS, vvCTS); break; |
duke@435 | 1513 | |
duke@435 | 1514 | case Bytecodes::_lshl: |
duke@435 | 1515 | case Bytecodes::_lshr: |
duke@435 | 1516 | case Bytecodes::_lushr: pp(vvvCTS, vvCTS); break; |
duke@435 | 1517 | |
duke@435 | 1518 | case Bytecodes::_i2l: |
duke@435 | 1519 | case Bytecodes::_i2d: |
duke@435 | 1520 | case Bytecodes::_f2l: |
duke@435 | 1521 | case Bytecodes::_f2d: pp(vCTS, vvCTS); break; |
duke@435 | 1522 | |
duke@435 | 1523 | case Bytecodes::_lcmp: pp(vvvvCTS, vCTS); break; |
duke@435 | 1524 | case Bytecodes::_dcmpl: |
duke@435 | 1525 | case Bytecodes::_dcmpg: pp(vvvvCTS, vCTS); break; |
duke@435 | 1526 | |
duke@435 | 1527 | case Bytecodes::_ifeq: |
duke@435 | 1528 | case Bytecodes::_ifne: |
duke@435 | 1529 | case Bytecodes::_iflt: |
duke@435 | 1530 | case Bytecodes::_ifge: |
duke@435 | 1531 | case Bytecodes::_ifgt: |
duke@435 | 1532 | case Bytecodes::_ifle: |
duke@435 | 1533 | case Bytecodes::_tableswitch: ppop1(valCTS); |
duke@435 | 1534 | break; |
duke@435 | 1535 | case Bytecodes::_ireturn: |
duke@435 | 1536 | case Bytecodes::_freturn: do_return_monitor_check(); |
duke@435 | 1537 | ppop1(valCTS); |
duke@435 | 1538 | break; |
duke@435 | 1539 | case Bytecodes::_if_icmpeq: |
duke@435 | 1540 | case Bytecodes::_if_icmpne: |
duke@435 | 1541 | case Bytecodes::_if_icmplt: |
duke@435 | 1542 | case Bytecodes::_if_icmpge: |
duke@435 | 1543 | case Bytecodes::_if_icmpgt: |
duke@435 | 1544 | case Bytecodes::_if_icmple: ppop(vvCTS); |
duke@435 | 1545 | break; |
duke@435 | 1546 | |
duke@435 | 1547 | case Bytecodes::_lreturn: do_return_monitor_check(); |
duke@435 | 1548 | ppop(vvCTS); |
duke@435 | 1549 | break; |
duke@435 | 1550 | |
duke@435 | 1551 | case Bytecodes::_dreturn: do_return_monitor_check(); |
duke@435 | 1552 | ppop(vvCTS); |
duke@435 | 1553 | break; |
duke@435 | 1554 | |
duke@435 | 1555 | case Bytecodes::_if_acmpeq: |
duke@435 | 1556 | case Bytecodes::_if_acmpne: ppop(rrCTS); break; |
duke@435 | 1557 | |
duke@435 | 1558 | case Bytecodes::_jsr: do_jsr(itr->dest()); break; |
duke@435 | 1559 | case Bytecodes::_jsr_w: do_jsr(itr->dest_w()); break; |
duke@435 | 1560 | |
duke@435 | 1561 | case Bytecodes::_getstatic: do_field(true, true, |
duke@435 | 1562 | itr->get_index_big(), |
duke@435 | 1563 | itr->bci()); break; |
duke@435 | 1564 | case Bytecodes::_putstatic: do_field(false, true, itr->get_index_big(), itr->bci()); break; |
duke@435 | 1565 | case Bytecodes::_getfield: do_field(true, false, itr->get_index_big(), itr->bci()); break; |
duke@435 | 1566 | case Bytecodes::_putfield: do_field(false, false, itr->get_index_big(), itr->bci()); break; |
duke@435 | 1567 | |
duke@435 | 1568 | case Bytecodes::_invokevirtual: |
duke@435 | 1569 | case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; |
duke@435 | 1570 | case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break; |
duke@435 | 1571 | case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break; |
duke@435 | 1572 | case Bytecodes::_newarray: |
duke@435 | 1573 | case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; |
duke@435 | 1574 | case Bytecodes::_checkcast: do_checkcast(); break; |
duke@435 | 1575 | case Bytecodes::_arraylength: |
duke@435 | 1576 | case Bytecodes::_instanceof: pp(rCTS, vCTS); break; |
duke@435 | 1577 | case Bytecodes::_monitorenter: do_monitorenter(itr->bci()); break; |
duke@435 | 1578 | case Bytecodes::_monitorexit: do_monitorexit(itr->bci()); break; |
duke@435 | 1579 | |
duke@435 | 1580 | case Bytecodes::_athrow: // handled by do_exception_edge() BUT ... |
duke@435 | 1581 | // vlh(apple): do_exception_edge() does not get |
duke@435 | 1582 | // called if method has no exception handlers |
duke@435 | 1583 | if ((!_has_exceptions) && (_monitor_top > 0)) { |
duke@435 | 1584 | _monitor_safe = false; |
duke@435 | 1585 | } |
duke@435 | 1586 | break; |
duke@435 | 1587 | |
duke@435 | 1588 | case Bytecodes::_areturn: do_return_monitor_check(); |
duke@435 | 1589 | ppop1(refCTS); |
duke@435 | 1590 | break; |
duke@435 | 1591 | case Bytecodes::_ifnull: |
duke@435 | 1592 | case Bytecodes::_ifnonnull: ppop1(refCTS); break; |
duke@435 | 1593 | case Bytecodes::_multianewarray: do_multianewarray(*(itr->bcp()+3), itr->bci()); break; |
duke@435 | 1594 | |
duke@435 | 1595 | case Bytecodes::_wide: fatal("Iterator should skip this bytecode"); break; |
duke@435 | 1596 | case Bytecodes::_ret: break; |
duke@435 | 1597 | |
duke@435 | 1598 | // Java opcodes |
duke@435 | 1599 | case Bytecodes::_lookupswitch: ppop1(valCTS); break; |
duke@435 | 1600 | |
duke@435 | 1601 | default: |
duke@435 | 1602 | tty->print("unexpected opcode: %d\n", itr->code()); |
duke@435 | 1603 | ShouldNotReachHere(); |
duke@435 | 1604 | break; |
duke@435 | 1605 | } |
duke@435 | 1606 | } |
duke@435 | 1607 | |
duke@435 | 1608 | void GenerateOopMap::check_type(CellTypeState expected, CellTypeState actual) { |
duke@435 | 1609 | if (!expected.equal_kind(actual)) { |
duke@435 | 1610 | verify_error("wrong type on stack (found: %c expected: %c)", actual.to_char(), expected.to_char()); |
duke@435 | 1611 | } |
duke@435 | 1612 | } |
duke@435 | 1613 | |
duke@435 | 1614 | void GenerateOopMap::ppstore(CellTypeState *in, int loc_no) { |
duke@435 | 1615 | while(!(*in).is_bottom()) { |
duke@435 | 1616 | CellTypeState expected =*in++; |
duke@435 | 1617 | CellTypeState actual = pop(); |
duke@435 | 1618 | check_type(expected, actual); |
duke@435 | 1619 | assert(loc_no >= 0, "sanity check"); |
duke@435 | 1620 | set_var(loc_no++, actual); |
duke@435 | 1621 | } |
duke@435 | 1622 | } |
duke@435 | 1623 | |
duke@435 | 1624 | void GenerateOopMap::ppload(CellTypeState *out, int loc_no) { |
duke@435 | 1625 | while(!(*out).is_bottom()) { |
duke@435 | 1626 | CellTypeState out1 = *out++; |
duke@435 | 1627 | CellTypeState vcts = get_var(loc_no); |
duke@435 | 1628 | assert(out1.can_be_reference() || out1.can_be_value(), |
duke@435 | 1629 | "can only load refs. and values."); |
duke@435 | 1630 | if (out1.is_reference()) { |
duke@435 | 1631 | assert(loc_no>=0, "sanity check"); |
duke@435 | 1632 | if (!vcts.is_reference()) { |
duke@435 | 1633 | // We were asked to push a reference, but the type of the |
duke@435 | 1634 | // variable can be something else |
duke@435 | 1635 | _conflict = true; |
duke@435 | 1636 | if (vcts.can_be_uninit()) { |
duke@435 | 1637 | // It is a ref-uninit conflict (at least). If there are other |
duke@435 | 1638 | // problems, we'll get them in the next round |
duke@435 | 1639 | add_to_ref_init_set(loc_no); |
duke@435 | 1640 | vcts = out1; |
duke@435 | 1641 | } else { |
duke@435 | 1642 | // It wasn't a ref-uninit conflict. So must be a |
duke@435 | 1643 | // ref-val or ref-pc conflict. Split the variable. |
duke@435 | 1644 | record_refval_conflict(loc_no); |
duke@435 | 1645 | vcts = out1; |
duke@435 | 1646 | } |
duke@435 | 1647 | push(out1); // recover... |
duke@435 | 1648 | } else { |
duke@435 | 1649 | push(vcts); // preserve reference. |
duke@435 | 1650 | } |
duke@435 | 1651 | // Otherwise it is a conflict, but one that verification would |
duke@435 | 1652 | // have caught if illegal. In particular, it can't be a topCTS |
duke@435 | 1653 | // resulting from mergeing two difference pcCTS's since the verifier |
duke@435 | 1654 | // would have rejected any use of such a merge. |
duke@435 | 1655 | } else { |
duke@435 | 1656 | push(out1); // handle val/init conflict |
duke@435 | 1657 | } |
duke@435 | 1658 | loc_no++; |
duke@435 | 1659 | } |
duke@435 | 1660 | } |
duke@435 | 1661 | |
duke@435 | 1662 | void GenerateOopMap::ppdupswap(int poplen, const char *out) { |
duke@435 | 1663 | CellTypeState actual[5]; |
duke@435 | 1664 | assert(poplen < 5, "this must be less than length of actual vector"); |
duke@435 | 1665 | |
duke@435 | 1666 | // pop all arguments |
duke@435 | 1667 | for(int i = 0; i < poplen; i++) actual[i] = pop(); |
duke@435 | 1668 | |
duke@435 | 1669 | // put them back |
duke@435 | 1670 | char push_ch = *out++; |
duke@435 | 1671 | while (push_ch != '\0') { |
duke@435 | 1672 | int idx = push_ch - '1'; |
duke@435 | 1673 | assert(idx >= 0 && idx < poplen, "wrong arguments"); |
duke@435 | 1674 | push(actual[idx]); |
duke@435 | 1675 | push_ch = *out++; |
duke@435 | 1676 | } |
duke@435 | 1677 | } |
duke@435 | 1678 | |
duke@435 | 1679 | void GenerateOopMap::ppop1(CellTypeState out) { |
duke@435 | 1680 | CellTypeState actual = pop(); |
duke@435 | 1681 | check_type(out, actual); |
duke@435 | 1682 | } |
duke@435 | 1683 | |
duke@435 | 1684 | void GenerateOopMap::ppop(CellTypeState *out) { |
duke@435 | 1685 | while (!(*out).is_bottom()) { |
duke@435 | 1686 | ppop1(*out++); |
duke@435 | 1687 | } |
duke@435 | 1688 | } |
duke@435 | 1689 | |
duke@435 | 1690 | void GenerateOopMap::ppush1(CellTypeState in) { |
duke@435 | 1691 | assert(in.is_reference() | in.is_value(), "sanity check"); |
duke@435 | 1692 | push(in); |
duke@435 | 1693 | } |
duke@435 | 1694 | |
duke@435 | 1695 | void GenerateOopMap::ppush(CellTypeState *in) { |
duke@435 | 1696 | while (!(*in).is_bottom()) { |
duke@435 | 1697 | ppush1(*in++); |
duke@435 | 1698 | } |
duke@435 | 1699 | } |
duke@435 | 1700 | |
duke@435 | 1701 | void GenerateOopMap::pp(CellTypeState *in, CellTypeState *out) { |
duke@435 | 1702 | ppop(in); |
duke@435 | 1703 | ppush(out); |
duke@435 | 1704 | } |
duke@435 | 1705 | |
duke@435 | 1706 | void GenerateOopMap::pp_new_ref(CellTypeState *in, int bci) { |
duke@435 | 1707 | ppop(in); |
duke@435 | 1708 | ppush1(CellTypeState::make_line_ref(bci)); |
duke@435 | 1709 | } |
duke@435 | 1710 | |
duke@435 | 1711 | void GenerateOopMap::ppop_any(int poplen) { |
duke@435 | 1712 | if (_stack_top >= poplen) { |
duke@435 | 1713 | _stack_top -= poplen; |
duke@435 | 1714 | } else { |
duke@435 | 1715 | verify_error("stack underflow"); |
duke@435 | 1716 | } |
duke@435 | 1717 | } |
duke@435 | 1718 | |
duke@435 | 1719 | // Replace all occurences of the state 'match' with the state 'replace' |
duke@435 | 1720 | // in our current state vector. |
duke@435 | 1721 | void GenerateOopMap::replace_all_CTS_matches(CellTypeState match, |
duke@435 | 1722 | CellTypeState replace) { |
duke@435 | 1723 | int i; |
duke@435 | 1724 | int len = _max_locals + _stack_top; |
duke@435 | 1725 | bool change = false; |
duke@435 | 1726 | |
duke@435 | 1727 | for (i = len - 1; i >= 0; i--) { |
duke@435 | 1728 | if (match.equal(_state[i])) { |
duke@435 | 1729 | _state[i] = replace; |
duke@435 | 1730 | } |
duke@435 | 1731 | } |
duke@435 | 1732 | |
duke@435 | 1733 | if (_monitor_top > 0) { |
duke@435 | 1734 | int base = _max_locals + _max_stack; |
duke@435 | 1735 | len = base + _monitor_top; |
duke@435 | 1736 | for (i = len - 1; i >= base; i--) { |
duke@435 | 1737 | if (match.equal(_state[i])) { |
duke@435 | 1738 | _state[i] = replace; |
duke@435 | 1739 | } |
duke@435 | 1740 | } |
duke@435 | 1741 | } |
duke@435 | 1742 | } |
duke@435 | 1743 | |
duke@435 | 1744 | void GenerateOopMap::do_checkcast() { |
duke@435 | 1745 | CellTypeState actual = pop(); |
duke@435 | 1746 | check_type(refCTS, actual); |
duke@435 | 1747 | push(actual); |
duke@435 | 1748 | } |
duke@435 | 1749 | |
duke@435 | 1750 | void GenerateOopMap::do_monitorenter(int bci) { |
duke@435 | 1751 | CellTypeState actual = pop(); |
duke@435 | 1752 | if (_monitor_top == bad_monitors) { |
duke@435 | 1753 | return; |
duke@435 | 1754 | } |
duke@435 | 1755 | |
duke@435 | 1756 | // Bail out when we get repeated locks on an identical monitor. This case |
duke@435 | 1757 | // isn't too hard to handle and can be made to work if supporting nested |
duke@435 | 1758 | // redundant synchronized statements becomes a priority. |
duke@435 | 1759 | // |
duke@435 | 1760 | // See also "Note" in do_monitorexit(), below. |
duke@435 | 1761 | if (actual.is_lock_reference()) { |
duke@435 | 1762 | _monitor_top = bad_monitors; |
duke@435 | 1763 | _monitor_safe = false; |
duke@435 | 1764 | |
duke@435 | 1765 | if (TraceMonitorMismatch) { |
duke@435 | 1766 | report_monitor_mismatch("nested redundant lock -- bailout..."); |
duke@435 | 1767 | } |
duke@435 | 1768 | return; |
duke@435 | 1769 | } |
duke@435 | 1770 | |
duke@435 | 1771 | CellTypeState lock = CellTypeState::make_lock_ref(bci); |
duke@435 | 1772 | check_type(refCTS, actual); |
duke@435 | 1773 | if (!actual.is_info_top()) { |
duke@435 | 1774 | replace_all_CTS_matches(actual, lock); |
duke@435 | 1775 | monitor_push(lock); |
duke@435 | 1776 | } |
duke@435 | 1777 | } |
duke@435 | 1778 | |
duke@435 | 1779 | void GenerateOopMap::do_monitorexit(int bci) { |
duke@435 | 1780 | CellTypeState actual = pop(); |
duke@435 | 1781 | if (_monitor_top == bad_monitors) { |
duke@435 | 1782 | return; |
duke@435 | 1783 | } |
duke@435 | 1784 | check_type(refCTS, actual); |
duke@435 | 1785 | CellTypeState expected = monitor_pop(); |
duke@435 | 1786 | if (!actual.is_lock_reference() || !expected.equal(actual)) { |
duke@435 | 1787 | // The monitor we are exiting is not verifiably the one |
duke@435 | 1788 | // on the top of our monitor stack. This causes a monitor |
duke@435 | 1789 | // mismatch. |
duke@435 | 1790 | _monitor_top = bad_monitors; |
duke@435 | 1791 | _monitor_safe = false; |
duke@435 | 1792 | |
duke@435 | 1793 | // We need to mark this basic block as changed so that |
duke@435 | 1794 | // this monitorexit will be visited again. We need to |
duke@435 | 1795 | // do this to ensure that we have accounted for the |
duke@435 | 1796 | // possibility that this bytecode will throw an |
duke@435 | 1797 | // exception. |
duke@435 | 1798 | BasicBlock* bb = get_basic_block_containing(bci); |
duke@435 | 1799 | bb->set_changed(true); |
duke@435 | 1800 | bb->_monitor_top = bad_monitors; |
duke@435 | 1801 | |
duke@435 | 1802 | if (TraceMonitorMismatch) { |
duke@435 | 1803 | report_monitor_mismatch("improper monitor pair"); |
duke@435 | 1804 | } |
duke@435 | 1805 | } else { |
duke@435 | 1806 | // This code is a fix for the case where we have repeated |
duke@435 | 1807 | // locking of the same object in straightline code. We clear |
duke@435 | 1808 | // out the lock when it is popped from the monitor stack |
duke@435 | 1809 | // and replace it with an unobtrusive reference value that can |
duke@435 | 1810 | // be locked again. |
duke@435 | 1811 | // |
duke@435 | 1812 | // Note: when generateOopMap is fixed to properly handle repeated, |
duke@435 | 1813 | // nested, redundant locks on the same object, then this |
duke@435 | 1814 | // fix will need to be removed at that time. |
duke@435 | 1815 | replace_all_CTS_matches(actual, CellTypeState::make_line_ref(bci)); |
duke@435 | 1816 | } |
duke@435 | 1817 | } |
duke@435 | 1818 | |
duke@435 | 1819 | void GenerateOopMap::do_return_monitor_check() { |
duke@435 | 1820 | if (_monitor_top > 0) { |
duke@435 | 1821 | // The monitor stack must be empty when we leave the method |
duke@435 | 1822 | // for the monitors to be properly matched. |
duke@435 | 1823 | _monitor_safe = false; |
duke@435 | 1824 | |
duke@435 | 1825 | // Since there are no successors to the *return bytecode, it |
duke@435 | 1826 | // isn't necessary to set _monitor_top to bad_monitors. |
duke@435 | 1827 | |
duke@435 | 1828 | if (TraceMonitorMismatch) { |
duke@435 | 1829 | report_monitor_mismatch("non-empty monitor stack at return"); |
duke@435 | 1830 | } |
duke@435 | 1831 | } |
duke@435 | 1832 | } |
duke@435 | 1833 | |
duke@435 | 1834 | void GenerateOopMap::do_jsr(int targ_bci) { |
duke@435 | 1835 | push(CellTypeState::make_addr(targ_bci)); |
duke@435 | 1836 | } |
duke@435 | 1837 | |
duke@435 | 1838 | |
duke@435 | 1839 | |
duke@435 | 1840 | void GenerateOopMap::do_ldc(int idx, int bci) { |
duke@435 | 1841 | constantPoolOop cp = method()->constants(); |
duke@435 | 1842 | constantTag tag = cp->tag_at(idx); |
duke@435 | 1843 | |
duke@435 | 1844 | CellTypeState cts = (tag.is_string() || tag.is_unresolved_string() || |
duke@435 | 1845 | tag.is_klass() || tag.is_unresolved_klass()) |
duke@435 | 1846 | ? CellTypeState::make_line_ref(bci) : valCTS; |
duke@435 | 1847 | ppush1(cts); |
duke@435 | 1848 | } |
duke@435 | 1849 | |
duke@435 | 1850 | void GenerateOopMap::do_multianewarray(int dims, int bci) { |
duke@435 | 1851 | assert(dims >= 1, "sanity check"); |
duke@435 | 1852 | for(int i = dims -1; i >=0; i--) { |
duke@435 | 1853 | ppop1(valCTS); |
duke@435 | 1854 | } |
duke@435 | 1855 | ppush1(CellTypeState::make_line_ref(bci)); |
duke@435 | 1856 | } |
duke@435 | 1857 | |
duke@435 | 1858 | void GenerateOopMap::do_astore(int idx) { |
duke@435 | 1859 | CellTypeState r_or_p = pop(); |
duke@435 | 1860 | if (!r_or_p.is_address() && !r_or_p.is_reference()) { |
duke@435 | 1861 | // We actually expected ref or pc, but we only report that we expected a ref. It does not |
duke@435 | 1862 | // really matter (at least for now) |
duke@435 | 1863 | verify_error("wrong type on stack (found: %c, expected: {pr})", r_or_p.to_char()); |
duke@435 | 1864 | return; |
duke@435 | 1865 | } |
duke@435 | 1866 | set_var(idx, r_or_p); |
duke@435 | 1867 | } |
duke@435 | 1868 | |
duke@435 | 1869 | // Copies bottom/zero terminated CTS string from "src" into "dst". |
duke@435 | 1870 | // Does NOT terminate with a bottom. Returns the number of cells copied. |
duke@435 | 1871 | int GenerateOopMap::copy_cts(CellTypeState *dst, CellTypeState *src) { |
duke@435 | 1872 | int idx = 0; |
duke@435 | 1873 | while (!src[idx].is_bottom()) { |
duke@435 | 1874 | dst[idx] = src[idx]; |
duke@435 | 1875 | idx++; |
duke@435 | 1876 | } |
duke@435 | 1877 | return idx; |
duke@435 | 1878 | } |
duke@435 | 1879 | |
duke@435 | 1880 | void GenerateOopMap::do_field(int is_get, int is_static, int idx, int bci) { |
duke@435 | 1881 | // Dig up signature for field in constant pool |
duke@435 | 1882 | constantPoolOop cp = method()->constants(); |
duke@435 | 1883 | int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); |
duke@435 | 1884 | int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); |
duke@435 | 1885 | symbolOop signature = cp->symbol_at(signatureIdx); |
duke@435 | 1886 | |
duke@435 | 1887 | // Parse signature (espcially simple for fields) |
duke@435 | 1888 | assert(signature->utf8_length() > 0, "field signatures cannot have zero length"); |
duke@435 | 1889 | // The signature is UFT8 encoded, but the first char is always ASCII for signatures. |
duke@435 | 1890 | char sigch = (char)*(signature->base()); |
duke@435 | 1891 | CellTypeState temp[4]; |
duke@435 | 1892 | CellTypeState *eff = sigchar_to_effect(sigch, bci, temp); |
duke@435 | 1893 | |
duke@435 | 1894 | CellTypeState in[4]; |
duke@435 | 1895 | CellTypeState *out; |
duke@435 | 1896 | int i = 0; |
duke@435 | 1897 | |
duke@435 | 1898 | if (is_get) { |
duke@435 | 1899 | out = eff; |
duke@435 | 1900 | } else { |
duke@435 | 1901 | out = epsilonCTS; |
duke@435 | 1902 | i = copy_cts(in, eff); |
duke@435 | 1903 | } |
duke@435 | 1904 | if (!is_static) in[i++] = CellTypeState::ref; |
duke@435 | 1905 | in[i] = CellTypeState::bottom; |
duke@435 | 1906 | assert(i<=3, "sanity check"); |
duke@435 | 1907 | pp(in, out); |
duke@435 | 1908 | } |
duke@435 | 1909 | |
duke@435 | 1910 | void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) { |
duke@435 | 1911 | // Dig up signature for field in constant pool |
duke@435 | 1912 | constantPoolOop cp = _method->constants(); |
duke@435 | 1913 | int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); |
duke@435 | 1914 | int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); |
duke@435 | 1915 | symbolOop signature = cp->symbol_at(signatureIdx); |
duke@435 | 1916 | |
duke@435 | 1917 | // Parse method signature |
duke@435 | 1918 | CellTypeState out[4]; |
duke@435 | 1919 | CellTypeState in[MAXARGSIZE+1]; // Includes result |
duke@435 | 1920 | ComputeCallStack cse(signature); |
duke@435 | 1921 | |
duke@435 | 1922 | // Compute return type |
duke@435 | 1923 | int res_length= cse.compute_for_returntype(out); |
duke@435 | 1924 | |
duke@435 | 1925 | // Temporary hack. |
duke@435 | 1926 | if (out[0].equal(CellTypeState::ref) && out[1].equal(CellTypeState::bottom)) { |
duke@435 | 1927 | out[0] = CellTypeState::make_line_ref(bci); |
duke@435 | 1928 | } |
duke@435 | 1929 | |
duke@435 | 1930 | assert(res_length<=4, "max value should be vv"); |
duke@435 | 1931 | |
duke@435 | 1932 | // Compute arguments |
duke@435 | 1933 | int arg_length = cse.compute_for_parameters(is_static != 0, in); |
duke@435 | 1934 | assert(arg_length<=MAXARGSIZE, "too many locals"); |
duke@435 | 1935 | |
duke@435 | 1936 | // Pop arguments |
duke@435 | 1937 | for (int i = arg_length - 1; i >= 0; i--) ppop1(in[i]);// Do args in reverse order. |
duke@435 | 1938 | |
duke@435 | 1939 | // Report results |
duke@435 | 1940 | if (_report_result_for_send == true) { |
duke@435 | 1941 | fill_stackmap_for_opcodes(_itr_send, vars(), stack(), _stack_top); |
duke@435 | 1942 | _report_result_for_send = false; |
duke@435 | 1943 | } |
duke@435 | 1944 | |
duke@435 | 1945 | // Push return address |
duke@435 | 1946 | ppush(out); |
duke@435 | 1947 | } |
duke@435 | 1948 | |
duke@435 | 1949 | // This is used to parse the signature for fields, since they are very simple... |
duke@435 | 1950 | CellTypeState *GenerateOopMap::sigchar_to_effect(char sigch, int bci, CellTypeState *out) { |
duke@435 | 1951 | // Object and array |
duke@435 | 1952 | if (sigch=='L' || sigch=='[') { |
duke@435 | 1953 | out[0] = CellTypeState::make_line_ref(bci); |
duke@435 | 1954 | out[1] = CellTypeState::bottom; |
duke@435 | 1955 | return out; |
duke@435 | 1956 | } |
duke@435 | 1957 | if (sigch == 'J' || sigch == 'D' ) return vvCTS; // Long and Double |
duke@435 | 1958 | if (sigch == 'V' ) return epsilonCTS; // Void |
duke@435 | 1959 | return vCTS; // Otherwise |
duke@435 | 1960 | } |
duke@435 | 1961 | |
duke@435 | 1962 | long GenerateOopMap::_total_byte_count = 0; |
duke@435 | 1963 | elapsedTimer GenerateOopMap::_total_oopmap_time; |
duke@435 | 1964 | |
duke@435 | 1965 | // This function assumes "bcs" is at a "ret" instruction and that the vars |
duke@435 | 1966 | // state is valid for that instruction. Furthermore, the ret instruction |
duke@435 | 1967 | // must be the last instruction in "bb" (we store information about the |
duke@435 | 1968 | // "ret" in "bb"). |
duke@435 | 1969 | void GenerateOopMap::ret_jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int varNo, int *data) { |
duke@435 | 1970 | CellTypeState ra = vars()[varNo]; |
duke@435 | 1971 | if (!ra.is_good_address()) { |
duke@435 | 1972 | verify_error("ret returns from two jsr subroutines?"); |
duke@435 | 1973 | return; |
duke@435 | 1974 | } |
duke@435 | 1975 | int target = ra.get_info(); |
duke@435 | 1976 | |
duke@435 | 1977 | RetTableEntry* rtEnt = _rt.find_jsrs_for_target(target); |
duke@435 | 1978 | int bci = bcs->bci(); |
duke@435 | 1979 | for (int i = 0; i < rtEnt->nof_jsrs(); i++) { |
duke@435 | 1980 | int target_bci = rtEnt->jsrs(i); |
duke@435 | 1981 | // Make sure a jrtRet does not set the changed bit for dead basicblock. |
duke@435 | 1982 | BasicBlock* jsr_bb = get_basic_block_containing(target_bci - 1); |
duke@435 | 1983 | debug_only(BasicBlock* target_bb = &jsr_bb[1];) |
duke@435 | 1984 | assert(target_bb == get_basic_block_at(target_bci), "wrong calc. of successor basicblock"); |
duke@435 | 1985 | bool alive = jsr_bb->is_alive(); |
duke@435 | 1986 | if (TraceNewOopMapGeneration) { |
duke@435 | 1987 | tty->print("pc = %d, ret -> %d alive: %s\n", bci, target_bci, alive ? "true" : "false"); |
duke@435 | 1988 | } |
duke@435 | 1989 | if (alive) jmpFct(this, target_bci, data); |
duke@435 | 1990 | } |
duke@435 | 1991 | } |
duke@435 | 1992 | |
duke@435 | 1993 | // |
duke@435 | 1994 | // Debug method |
duke@435 | 1995 | // |
duke@435 | 1996 | char* GenerateOopMap::state_vec_to_string(CellTypeState* vec, int len) { |
duke@435 | 1997 | #ifdef ASSERT |
duke@435 | 1998 | int checklen = MAX3(_max_locals, _max_stack, _max_monitors) + 1; |
duke@435 | 1999 | assert(len < checklen, "state_vec_buf overflow"); |
duke@435 | 2000 | #endif |
duke@435 | 2001 | for (int i = 0; i < len; i++) _state_vec_buf[i] = vec[i].to_char(); |
duke@435 | 2002 | _state_vec_buf[len] = 0; |
duke@435 | 2003 | return _state_vec_buf; |
duke@435 | 2004 | } |
duke@435 | 2005 | |
duke@435 | 2006 | void GenerateOopMap::print_time() { |
duke@435 | 2007 | tty->print_cr ("Accumulated oopmap times:"); |
duke@435 | 2008 | tty->print_cr ("---------------------------"); |
duke@435 | 2009 | tty->print_cr (" Total : %3.3f sec.", GenerateOopMap::_total_oopmap_time.seconds()); |
duke@435 | 2010 | tty->print_cr (" (%3.0f bytecodes per sec) ", |
duke@435 | 2011 | GenerateOopMap::_total_byte_count / GenerateOopMap::_total_oopmap_time.seconds()); |
duke@435 | 2012 | } |
duke@435 | 2013 | |
duke@435 | 2014 | // |
duke@435 | 2015 | // ============ Main Entry Point =========== |
duke@435 | 2016 | // |
duke@435 | 2017 | GenerateOopMap::GenerateOopMap(methodHandle method) { |
duke@435 | 2018 | // We have to initialize all variables here, that can be queried direcly |
duke@435 | 2019 | _method = method; |
duke@435 | 2020 | _max_locals=0; |
duke@435 | 2021 | _init_vars = NULL; |
duke@435 | 2022 | |
duke@435 | 2023 | #ifndef PRODUCT |
duke@435 | 2024 | // If we are doing a detailed trace, include the regular trace information. |
duke@435 | 2025 | if (TraceNewOopMapGenerationDetailed) { |
duke@435 | 2026 | TraceNewOopMapGeneration = true; |
duke@435 | 2027 | } |
duke@435 | 2028 | #endif |
duke@435 | 2029 | } |
duke@435 | 2030 | |
duke@435 | 2031 | void GenerateOopMap::compute_map(TRAPS) { |
duke@435 | 2032 | #ifndef PRODUCT |
duke@435 | 2033 | if (TimeOopMap2) { |
duke@435 | 2034 | method()->print_short_name(tty); |
duke@435 | 2035 | tty->print(" "); |
duke@435 | 2036 | } |
duke@435 | 2037 | if (TimeOopMap) { |
duke@435 | 2038 | _total_byte_count += method()->code_size(); |
duke@435 | 2039 | } |
duke@435 | 2040 | #endif |
duke@435 | 2041 | TraceTime t_single("oopmap time", TimeOopMap2); |
duke@435 | 2042 | TraceTime t_all(NULL, &_total_oopmap_time, TimeOopMap); |
duke@435 | 2043 | |
duke@435 | 2044 | // Initialize values |
duke@435 | 2045 | _got_error = false; |
duke@435 | 2046 | _conflict = false; |
duke@435 | 2047 | _max_locals = method()->max_locals(); |
duke@435 | 2048 | _max_stack = method()->max_stack(); |
duke@435 | 2049 | _has_exceptions = (method()->exception_table()->length() > 0); |
duke@435 | 2050 | _nof_refval_conflicts = 0; |
duke@435 | 2051 | _init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars |
duke@435 | 2052 | _report_result = false; |
duke@435 | 2053 | _report_result_for_send = false; |
duke@435 | 2054 | _new_var_map = NULL; |
duke@435 | 2055 | _ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number; |
duke@435 | 2056 | _did_rewriting = false; |
duke@435 | 2057 | _did_relocation = false; |
duke@435 | 2058 | |
duke@435 | 2059 | if (TraceNewOopMapGeneration) { |
duke@435 | 2060 | tty->print("Method name: %s\n", method()->name()->as_C_string()); |
duke@435 | 2061 | if (Verbose) { |
duke@435 | 2062 | _method->print_codes(); |
duke@435 | 2063 | tty->print_cr("Exception table:"); |
duke@435 | 2064 | typeArrayOop excps = method()->exception_table(); |
duke@435 | 2065 | for(int i = 0; i < excps->length(); i += 4) { |
duke@435 | 2066 | tty->print_cr("[%d - %d] -> %d", excps->int_at(i + 0), excps->int_at(i + 1), excps->int_at(i + 2)); |
duke@435 | 2067 | } |
duke@435 | 2068 | } |
duke@435 | 2069 | } |
duke@435 | 2070 | |
duke@435 | 2071 | // if no code - do nothing |
duke@435 | 2072 | // compiler needs info |
duke@435 | 2073 | if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) { |
duke@435 | 2074 | fill_stackmap_prolog(0); |
duke@435 | 2075 | fill_stackmap_epilog(); |
duke@435 | 2076 | return; |
duke@435 | 2077 | } |
duke@435 | 2078 | // Step 1: Compute all jump targets and their return value |
duke@435 | 2079 | if (!_got_error) |
duke@435 | 2080 | _rt.compute_ret_table(_method); |
duke@435 | 2081 | |
duke@435 | 2082 | // Step 2: Find all basic blocks and count GC points |
duke@435 | 2083 | if (!_got_error) |
duke@435 | 2084 | mark_bbheaders_and_count_gc_points(); |
duke@435 | 2085 | |
duke@435 | 2086 | // Step 3: Calculate stack maps |
duke@435 | 2087 | if (!_got_error) |
duke@435 | 2088 | do_interpretation(); |
duke@435 | 2089 | |
duke@435 | 2090 | // Step 4:Return results |
duke@435 | 2091 | if (!_got_error && report_results()) |
duke@435 | 2092 | report_result(); |
duke@435 | 2093 | |
duke@435 | 2094 | if (_got_error) { |
duke@435 | 2095 | THROW_HANDLE(_exception); |
duke@435 | 2096 | } |
duke@435 | 2097 | } |
duke@435 | 2098 | |
duke@435 | 2099 | // Error handling methods |
duke@435 | 2100 | // These methods create an exception for the current thread which is thrown |
duke@435 | 2101 | // at the bottom of the call stack, when it returns to compute_map(). The |
duke@435 | 2102 | // _got_error flag controls execution. NOT TODO: The VM exception propagation |
duke@435 | 2103 | // mechanism using TRAPS/CHECKs could be used here instead but it would need |
duke@435 | 2104 | // to be added as a parameter to every function and checked for every call. |
duke@435 | 2105 | // The tons of extra code it would generate didn't seem worth the change. |
duke@435 | 2106 | // |
duke@435 | 2107 | void GenerateOopMap::error_work(const char *format, va_list ap) { |
duke@435 | 2108 | _got_error = true; |
duke@435 | 2109 | char msg_buffer[512]; |
duke@435 | 2110 | vsnprintf(msg_buffer, sizeof(msg_buffer), format, ap); |
duke@435 | 2111 | // Append method name |
duke@435 | 2112 | char msg_buffer2[512]; |
duke@435 | 2113 | jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string()); |
duke@435 | 2114 | _exception = Exceptions::new_exception(Thread::current(), |
duke@435 | 2115 | vmSymbols::java_lang_LinkageError(), msg_buffer2); |
duke@435 | 2116 | } |
duke@435 | 2117 | |
duke@435 | 2118 | void GenerateOopMap::report_error(const char *format, ...) { |
duke@435 | 2119 | va_list ap; |
duke@435 | 2120 | va_start(ap, format); |
duke@435 | 2121 | error_work(format, ap); |
duke@435 | 2122 | } |
duke@435 | 2123 | |
duke@435 | 2124 | void GenerateOopMap::verify_error(const char *format, ...) { |
duke@435 | 2125 | // We do not distinguish between different types of errors for verification |
duke@435 | 2126 | // errors. Let the verifier give a better message. |
duke@435 | 2127 | const char *msg = "Illegal class file encountered. Try running with -Xverify:all"; |
duke@435 | 2128 | error_work(msg, NULL); |
duke@435 | 2129 | } |
duke@435 | 2130 | |
duke@435 | 2131 | // |
duke@435 | 2132 | // Report result opcodes |
duke@435 | 2133 | // |
duke@435 | 2134 | void GenerateOopMap::report_result() { |
duke@435 | 2135 | |
duke@435 | 2136 | if (TraceNewOopMapGeneration) tty->print_cr("Report result pass"); |
duke@435 | 2137 | |
duke@435 | 2138 | // We now want to report the result of the parse |
duke@435 | 2139 | _report_result = true; |
duke@435 | 2140 | |
duke@435 | 2141 | // Prolog code |
duke@435 | 2142 | fill_stackmap_prolog(_gc_points); |
duke@435 | 2143 | |
duke@435 | 2144 | // Mark everything changed, then do one interpretation pass. |
duke@435 | 2145 | for (int i = 0; i<_bb_count; i++) { |
duke@435 | 2146 | if (_basic_blocks[i].is_reachable()) { |
duke@435 | 2147 | _basic_blocks[i].set_changed(true); |
duke@435 | 2148 | interp_bb(&_basic_blocks[i]); |
duke@435 | 2149 | } |
duke@435 | 2150 | } |
duke@435 | 2151 | |
duke@435 | 2152 | // Note: Since we are skipping dead-code when we are reporting results, then |
duke@435 | 2153 | // the no. of encountered gc-points might be fewer than the previously number |
duke@435 | 2154 | // we have counted. (dead-code is a pain - it should be removed before we get here) |
duke@435 | 2155 | fill_stackmap_epilog(); |
duke@435 | 2156 | |
duke@435 | 2157 | // Report initvars |
duke@435 | 2158 | fill_init_vars(_init_vars); |
duke@435 | 2159 | |
duke@435 | 2160 | _report_result = false; |
duke@435 | 2161 | } |
duke@435 | 2162 | |
duke@435 | 2163 | void GenerateOopMap::result_for_basicblock(int bci) { |
duke@435 | 2164 | if (TraceNewOopMapGeneration) tty->print_cr("Report result pass for basicblock"); |
duke@435 | 2165 | |
duke@435 | 2166 | // We now want to report the result of the parse |
duke@435 | 2167 | _report_result = true; |
duke@435 | 2168 | |
duke@435 | 2169 | // Find basicblock and report results |
duke@435 | 2170 | BasicBlock* bb = get_basic_block_containing(bci); |
duke@435 | 2171 | assert(bb->is_reachable(), "getting result from unreachable basicblock"); |
duke@435 | 2172 | bb->set_changed(true); |
duke@435 | 2173 | interp_bb(bb); |
duke@435 | 2174 | } |
duke@435 | 2175 | |
duke@435 | 2176 | // |
duke@435 | 2177 | // Conflict handling code |
duke@435 | 2178 | // |
duke@435 | 2179 | |
duke@435 | 2180 | void GenerateOopMap::record_refval_conflict(int varNo) { |
duke@435 | 2181 | assert(varNo>=0 && varNo< _max_locals, "index out of range"); |
duke@435 | 2182 | |
duke@435 | 2183 | if (TraceOopMapRewrites) { |
duke@435 | 2184 | tty->print("### Conflict detected (local no: %d)\n", varNo); |
duke@435 | 2185 | } |
duke@435 | 2186 | |
duke@435 | 2187 | if (!_new_var_map) { |
duke@435 | 2188 | _new_var_map = NEW_RESOURCE_ARRAY(int, _max_locals); |
duke@435 | 2189 | for (int k = 0; k < _max_locals; k++) _new_var_map[k] = k; |
duke@435 | 2190 | } |
duke@435 | 2191 | |
duke@435 | 2192 | if ( _new_var_map[varNo] == varNo) { |
duke@435 | 2193 | // Check if max. number of locals has been reached |
duke@435 | 2194 | if (_max_locals + _nof_refval_conflicts >= MAX_LOCAL_VARS) { |
duke@435 | 2195 | report_error("Rewriting exceeded local variable limit"); |
duke@435 | 2196 | return; |
duke@435 | 2197 | } |
duke@435 | 2198 | _new_var_map[varNo] = _max_locals + _nof_refval_conflicts; |
duke@435 | 2199 | _nof_refval_conflicts++; |
duke@435 | 2200 | } |
duke@435 | 2201 | } |
duke@435 | 2202 | |
duke@435 | 2203 | void GenerateOopMap::rewrite_refval_conflicts() |
duke@435 | 2204 | { |
duke@435 | 2205 | // We can get here two ways: Either a rewrite conflict was detected, or |
duke@435 | 2206 | // an uninitialize reference was detected. In the second case, we do not |
duke@435 | 2207 | // do any rewriting, we just want to recompute the reference set with the |
duke@435 | 2208 | // new information |
duke@435 | 2209 | |
duke@435 | 2210 | int nof_conflicts = 0; // Used for debugging only |
duke@435 | 2211 | |
duke@435 | 2212 | if ( _nof_refval_conflicts == 0 ) |
duke@435 | 2213 | return; |
duke@435 | 2214 | |
duke@435 | 2215 | // Check if rewrites are allowed in this parse. |
duke@435 | 2216 | if (!allow_rewrites() && !IgnoreRewrites) { |
duke@435 | 2217 | fatal("Rewriting method not allowed at this stage"); |
duke@435 | 2218 | } |
duke@435 | 2219 | |
duke@435 | 2220 | |
duke@435 | 2221 | // This following flag is to tempoary supress rewrites. The locals that might conflict will |
duke@435 | 2222 | // all be set to contain values. This is UNSAFE - however, until the rewriting has been completely |
duke@435 | 2223 | // tested it is nice to have. |
duke@435 | 2224 | if (IgnoreRewrites) { |
duke@435 | 2225 | if (Verbose) { |
duke@435 | 2226 | tty->print("rewrites suppressed for local no. "); |
duke@435 | 2227 | for (int l = 0; l < _max_locals; l++) { |
duke@435 | 2228 | if (_new_var_map[l] != l) { |
duke@435 | 2229 | tty->print("%d ", l); |
duke@435 | 2230 | vars()[l] = CellTypeState::value; |
duke@435 | 2231 | } |
duke@435 | 2232 | } |
duke@435 | 2233 | tty->cr(); |
duke@435 | 2234 | } |
duke@435 | 2235 | |
duke@435 | 2236 | // That was that... |
duke@435 | 2237 | _new_var_map = NULL; |
duke@435 | 2238 | _nof_refval_conflicts = 0; |
duke@435 | 2239 | _conflict = false; |
duke@435 | 2240 | |
duke@435 | 2241 | return; |
duke@435 | 2242 | } |
duke@435 | 2243 | |
duke@435 | 2244 | // Tracing flag |
duke@435 | 2245 | _did_rewriting = true; |
duke@435 | 2246 | |
duke@435 | 2247 | if (TraceOopMapRewrites) { |
duke@435 | 2248 | tty->print_cr("ref/value conflict for method %s - bytecodes are getting rewritten", method()->name()->as_C_string()); |
duke@435 | 2249 | method()->print(); |
duke@435 | 2250 | method()->print_codes(); |
duke@435 | 2251 | } |
duke@435 | 2252 | |
duke@435 | 2253 | assert(_new_var_map!=NULL, "nothing to rewrite"); |
duke@435 | 2254 | assert(_conflict==true, "We should not be here"); |
duke@435 | 2255 | |
duke@435 | 2256 | compute_ret_adr_at_TOS(); |
duke@435 | 2257 | if (!_got_error) { |
duke@435 | 2258 | for (int k = 0; k < _max_locals && !_got_error; k++) { |
duke@435 | 2259 | if (_new_var_map[k] != k) { |
duke@435 | 2260 | if (TraceOopMapRewrites) { |
duke@435 | 2261 | tty->print_cr("Rewriting: %d -> %d", k, _new_var_map[k]); |
duke@435 | 2262 | } |
duke@435 | 2263 | rewrite_refval_conflict(k, _new_var_map[k]); |
duke@435 | 2264 | if (_got_error) return; |
duke@435 | 2265 | nof_conflicts++; |
duke@435 | 2266 | } |
duke@435 | 2267 | } |
duke@435 | 2268 | } |
duke@435 | 2269 | |
duke@435 | 2270 | assert(nof_conflicts == _nof_refval_conflicts, "sanity check"); |
duke@435 | 2271 | |
duke@435 | 2272 | // Adjust the number of locals |
duke@435 | 2273 | method()->set_max_locals(_max_locals+_nof_refval_conflicts); |
duke@435 | 2274 | _max_locals += _nof_refval_conflicts; |
duke@435 | 2275 | |
duke@435 | 2276 | // That was that... |
duke@435 | 2277 | _new_var_map = NULL; |
duke@435 | 2278 | _nof_refval_conflicts = 0; |
duke@435 | 2279 | } |
duke@435 | 2280 | |
duke@435 | 2281 | void GenerateOopMap::rewrite_refval_conflict(int from, int to) { |
duke@435 | 2282 | bool startOver; |
duke@435 | 2283 | do { |
duke@435 | 2284 | // Make sure that the BytecodeStream is constructed in the loop, since |
duke@435 | 2285 | // during rewriting a new method oop is going to be used, and the next time |
duke@435 | 2286 | // around we want to use that. |
duke@435 | 2287 | BytecodeStream bcs(_method); |
duke@435 | 2288 | startOver = false; |
duke@435 | 2289 | |
duke@435 | 2290 | while( bcs.next() >=0 && !startOver && !_got_error) { |
duke@435 | 2291 | startOver = rewrite_refval_conflict_inst(&bcs, from, to); |
duke@435 | 2292 | } |
duke@435 | 2293 | } while (startOver && !_got_error); |
duke@435 | 2294 | } |
duke@435 | 2295 | |
duke@435 | 2296 | /* If the current instruction is one that uses local variable "from" |
duke@435 | 2297 | in a ref way, change it to use "to". There's a subtle reason why we |
duke@435 | 2298 | renumber the ref uses and not the non-ref uses: non-ref uses may be |
duke@435 | 2299 | 2 slots wide (double, long) which would necessitate keeping track of |
duke@435 | 2300 | whether we should add one or two variables to the method. If the change |
duke@435 | 2301 | affected the width of some instruction, returns "TRUE"; otherwise, returns "FALSE". |
duke@435 | 2302 | Another reason for moving ref's value is for solving (addr, ref) conflicts, which |
duke@435 | 2303 | both uses aload/astore methods. |
duke@435 | 2304 | */ |
duke@435 | 2305 | bool GenerateOopMap::rewrite_refval_conflict_inst(BytecodeStream *itr, int from, int to) { |
duke@435 | 2306 | Bytecodes::Code bc = itr->code(); |
duke@435 | 2307 | int index; |
duke@435 | 2308 | int bci = itr->bci(); |
duke@435 | 2309 | |
duke@435 | 2310 | if (is_aload(itr, &index) && index == from) { |
duke@435 | 2311 | if (TraceOopMapRewrites) { |
duke@435 | 2312 | tty->print_cr("Rewriting aload at bci: %d", bci); |
duke@435 | 2313 | } |
duke@435 | 2314 | return rewrite_load_or_store(itr, Bytecodes::_aload, Bytecodes::_aload_0, to); |
duke@435 | 2315 | } |
duke@435 | 2316 | |
duke@435 | 2317 | if (is_astore(itr, &index) && index == from) { |
duke@435 | 2318 | if (!stack_top_holds_ret_addr(bci)) { |
duke@435 | 2319 | if (TraceOopMapRewrites) { |
duke@435 | 2320 | tty->print_cr("Rewriting astore at bci: %d", bci); |
duke@435 | 2321 | } |
duke@435 | 2322 | return rewrite_load_or_store(itr, Bytecodes::_astore, Bytecodes::_astore_0, to); |
duke@435 | 2323 | } else { |
duke@435 | 2324 | if (TraceOopMapRewrites) { |
duke@435 | 2325 | tty->print_cr("Supress rewriting of astore at bci: %d", bci); |
duke@435 | 2326 | } |
duke@435 | 2327 | } |
duke@435 | 2328 | } |
duke@435 | 2329 | |
duke@435 | 2330 | return false; |
duke@435 | 2331 | } |
duke@435 | 2332 | |
duke@435 | 2333 | // The argument to this method is: |
duke@435 | 2334 | // bc : Current bytecode |
duke@435 | 2335 | // bcN : either _aload or _astore |
duke@435 | 2336 | // bc0 : either _aload_0 or _astore_0 |
duke@435 | 2337 | bool GenerateOopMap::rewrite_load_or_store(BytecodeStream *bcs, Bytecodes::Code bcN, Bytecodes::Code bc0, unsigned int varNo) { |
duke@435 | 2338 | assert(bcN == Bytecodes::_astore || bcN == Bytecodes::_aload, "wrong argument (bcN)"); |
duke@435 | 2339 | assert(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0, "wrong argument (bc0)"); |
duke@435 | 2340 | int ilen = Bytecodes::length_at(bcs->bcp()); |
duke@435 | 2341 | int newIlen; |
duke@435 | 2342 | |
duke@435 | 2343 | if (ilen == 4) { |
duke@435 | 2344 | // Original instruction was wide; keep it wide for simplicity |
duke@435 | 2345 | newIlen = 4; |
duke@435 | 2346 | } else if (varNo < 4) |
duke@435 | 2347 | newIlen = 1; |
duke@435 | 2348 | else if (varNo >= 256) |
duke@435 | 2349 | newIlen = 4; |
duke@435 | 2350 | else |
duke@435 | 2351 | newIlen = 2; |
duke@435 | 2352 | |
duke@435 | 2353 | // If we need to relocate in order to patch the byte, we |
duke@435 | 2354 | // do the patching in a temp. buffer, that is passed to the reloc. |
duke@435 | 2355 | // The patching of the bytecode stream is then done by the Relocator. |
duke@435 | 2356 | // This is neccesary, since relocating the instruction at a certain bci, might |
duke@435 | 2357 | // also relocate that instruction, e.g., if a _goto before it gets widen to a _goto_w. |
duke@435 | 2358 | // Hence, we do not know which bci to patch after relocation. |
duke@435 | 2359 | |
duke@435 | 2360 | assert(newIlen <= 4, "sanity check"); |
duke@435 | 2361 | u_char inst_buffer[4]; // Max. instruction size is 4. |
duke@435 | 2362 | address bcp; |
duke@435 | 2363 | |
duke@435 | 2364 | if (newIlen != ilen) { |
duke@435 | 2365 | // Relocation needed do patching in temp. buffer |
duke@435 | 2366 | bcp = (address)inst_buffer; |
duke@435 | 2367 | } else { |
duke@435 | 2368 | bcp = _method->bcp_from(bcs->bci()); |
duke@435 | 2369 | } |
duke@435 | 2370 | |
duke@435 | 2371 | // Patch either directly in methodOop or in temp. buffer |
duke@435 | 2372 | if (newIlen == 1) { |
duke@435 | 2373 | assert(varNo < 4, "varNo too large"); |
duke@435 | 2374 | *bcp = bc0 + varNo; |
duke@435 | 2375 | } else if (newIlen == 2) { |
duke@435 | 2376 | assert(varNo < 256, "2-byte index needed!"); |
duke@435 | 2377 | *(bcp + 0) = bcN; |
duke@435 | 2378 | *(bcp + 1) = varNo; |
duke@435 | 2379 | } else { |
duke@435 | 2380 | assert(newIlen == 4, "Wrong instruction length"); |
duke@435 | 2381 | *(bcp + 0) = Bytecodes::_wide; |
duke@435 | 2382 | *(bcp + 1) = bcN; |
duke@435 | 2383 | Bytes::put_Java_u2(bcp+2, varNo); |
duke@435 | 2384 | } |
duke@435 | 2385 | |
duke@435 | 2386 | if (newIlen != ilen) { |
duke@435 | 2387 | expand_current_instr(bcs->bci(), ilen, newIlen, inst_buffer); |
duke@435 | 2388 | } |
duke@435 | 2389 | |
duke@435 | 2390 | |
duke@435 | 2391 | return (newIlen != ilen); |
duke@435 | 2392 | } |
duke@435 | 2393 | |
duke@435 | 2394 | class RelocCallback : public RelocatorListener { |
duke@435 | 2395 | private: |
duke@435 | 2396 | GenerateOopMap* _gom; |
duke@435 | 2397 | public: |
duke@435 | 2398 | RelocCallback(GenerateOopMap* gom) { _gom = gom; }; |
duke@435 | 2399 | |
duke@435 | 2400 | // Callback method |
duke@435 | 2401 | virtual void relocated(int bci, int delta, int new_code_length) { |
duke@435 | 2402 | _gom->update_basic_blocks (bci, delta, new_code_length); |
duke@435 | 2403 | _gom->update_ret_adr_at_TOS(bci, delta); |
duke@435 | 2404 | _gom->_rt.update_ret_table (bci, delta); |
duke@435 | 2405 | } |
duke@435 | 2406 | }; |
duke@435 | 2407 | |
duke@435 | 2408 | // Returns true if expanding was succesful. Otherwise, reports an error and |
duke@435 | 2409 | // returns false. |
duke@435 | 2410 | void GenerateOopMap::expand_current_instr(int bci, int ilen, int newIlen, u_char inst_buffer[]) { |
duke@435 | 2411 | Thread *THREAD = Thread::current(); // Could really have TRAPS argument. |
duke@435 | 2412 | RelocCallback rcb(this); |
duke@435 | 2413 | Relocator rc(_method, &rcb); |
duke@435 | 2414 | methodHandle m= rc.insert_space_at(bci, newIlen, inst_buffer, THREAD); |
duke@435 | 2415 | if (m.is_null() || HAS_PENDING_EXCEPTION) { |
duke@435 | 2416 | report_error("could not rewrite method - exception occurred or bytecode buffer overflow"); |
duke@435 | 2417 | return; |
duke@435 | 2418 | } |
duke@435 | 2419 | |
duke@435 | 2420 | // Relocator returns a new method oop. |
duke@435 | 2421 | _did_relocation = true; |
duke@435 | 2422 | _method = m; |
duke@435 | 2423 | } |
duke@435 | 2424 | |
duke@435 | 2425 | |
duke@435 | 2426 | bool GenerateOopMap::is_astore(BytecodeStream *itr, int *index) { |
duke@435 | 2427 | Bytecodes::Code bc = itr->code(); |
duke@435 | 2428 | switch(bc) { |
duke@435 | 2429 | case Bytecodes::_astore_0: |
duke@435 | 2430 | case Bytecodes::_astore_1: |
duke@435 | 2431 | case Bytecodes::_astore_2: |
duke@435 | 2432 | case Bytecodes::_astore_3: |
duke@435 | 2433 | *index = bc - Bytecodes::_astore_0; |
duke@435 | 2434 | return true; |
duke@435 | 2435 | case Bytecodes::_astore: |
duke@435 | 2436 | *index = itr->get_index(); |
duke@435 | 2437 | return true; |
duke@435 | 2438 | } |
duke@435 | 2439 | return false; |
duke@435 | 2440 | } |
duke@435 | 2441 | |
duke@435 | 2442 | bool GenerateOopMap::is_aload(BytecodeStream *itr, int *index) { |
duke@435 | 2443 | Bytecodes::Code bc = itr->code(); |
duke@435 | 2444 | switch(bc) { |
duke@435 | 2445 | case Bytecodes::_aload_0: |
duke@435 | 2446 | case Bytecodes::_aload_1: |
duke@435 | 2447 | case Bytecodes::_aload_2: |
duke@435 | 2448 | case Bytecodes::_aload_3: |
duke@435 | 2449 | *index = bc - Bytecodes::_aload_0; |
duke@435 | 2450 | return true; |
duke@435 | 2451 | |
duke@435 | 2452 | case Bytecodes::_aload: |
duke@435 | 2453 | *index = itr->get_index(); |
duke@435 | 2454 | return true; |
duke@435 | 2455 | } |
duke@435 | 2456 | return false; |
duke@435 | 2457 | } |
duke@435 | 2458 | |
duke@435 | 2459 | |
duke@435 | 2460 | // Return true iff the top of the operand stack holds a return address at |
duke@435 | 2461 | // the current instruction |
duke@435 | 2462 | bool GenerateOopMap::stack_top_holds_ret_addr(int bci) { |
duke@435 | 2463 | for(int i = 0; i < _ret_adr_tos->length(); i++) { |
duke@435 | 2464 | if (_ret_adr_tos->at(i) == bci) |
duke@435 | 2465 | return true; |
duke@435 | 2466 | } |
duke@435 | 2467 | |
duke@435 | 2468 | return false; |
duke@435 | 2469 | } |
duke@435 | 2470 | |
duke@435 | 2471 | void GenerateOopMap::compute_ret_adr_at_TOS() { |
duke@435 | 2472 | assert(_ret_adr_tos != NULL, "must be initialized"); |
duke@435 | 2473 | _ret_adr_tos->clear(); |
duke@435 | 2474 | |
duke@435 | 2475 | for (int i = 0; i < bb_count(); i++) { |
duke@435 | 2476 | BasicBlock* bb = &_basic_blocks[i]; |
duke@435 | 2477 | |
duke@435 | 2478 | // Make sure to only check basicblocks that are reachable |
duke@435 | 2479 | if (bb->is_reachable()) { |
duke@435 | 2480 | |
duke@435 | 2481 | // For each Basic block we check all instructions |
duke@435 | 2482 | BytecodeStream bcs(_method); |
duke@435 | 2483 | bcs.set_interval(bb->_bci, next_bb_start_pc(bb)); |
duke@435 | 2484 | |
duke@435 | 2485 | restore_state(bb); |
duke@435 | 2486 | |
duke@435 | 2487 | while (bcs.next()>=0 && !_got_error) { |
duke@435 | 2488 | // TDT: should this be is_good_address() ? |
duke@435 | 2489 | if (_stack_top > 0 && stack()[_stack_top-1].is_address()) { |
duke@435 | 2490 | _ret_adr_tos->append(bcs.bci()); |
duke@435 | 2491 | if (TraceNewOopMapGeneration) { |
duke@435 | 2492 | tty->print_cr("Ret_adr TOS at bci: %d", bcs.bci()); |
duke@435 | 2493 | } |
duke@435 | 2494 | } |
duke@435 | 2495 | interp1(&bcs); |
duke@435 | 2496 | } |
duke@435 | 2497 | } |
duke@435 | 2498 | } |
duke@435 | 2499 | } |
duke@435 | 2500 | |
duke@435 | 2501 | void GenerateOopMap::update_ret_adr_at_TOS(int bci, int delta) { |
duke@435 | 2502 | for(int i = 0; i < _ret_adr_tos->length(); i++) { |
duke@435 | 2503 | int v = _ret_adr_tos->at(i); |
duke@435 | 2504 | if (v > bci) _ret_adr_tos->at_put(i, v + delta); |
duke@435 | 2505 | } |
duke@435 | 2506 | } |
duke@435 | 2507 | |
duke@435 | 2508 | // =================================================================== |
duke@435 | 2509 | |
duke@435 | 2510 | #ifndef PRODUCT |
duke@435 | 2511 | int ResolveOopMapConflicts::_nof_invocations = 0; |
duke@435 | 2512 | int ResolveOopMapConflicts::_nof_rewrites = 0; |
duke@435 | 2513 | int ResolveOopMapConflicts::_nof_relocations = 0; |
duke@435 | 2514 | #endif |
duke@435 | 2515 | |
duke@435 | 2516 | methodHandle ResolveOopMapConflicts::do_potential_rewrite(TRAPS) { |
duke@435 | 2517 | compute_map(CHECK_(methodHandle())); |
duke@435 | 2518 | |
duke@435 | 2519 | #ifndef PRODUCT |
duke@435 | 2520 | // Tracking and statistics |
duke@435 | 2521 | if (PrintRewrites) { |
duke@435 | 2522 | _nof_invocations++; |
duke@435 | 2523 | if (did_rewriting()) { |
duke@435 | 2524 | _nof_rewrites++; |
duke@435 | 2525 | if (did_relocation()) _nof_relocations++; |
duke@435 | 2526 | tty->print("Method was rewritten %s: ", (did_relocation()) ? "and relocated" : ""); |
duke@435 | 2527 | method()->print_value(); tty->cr(); |
duke@435 | 2528 | tty->print_cr("Cand.: %d rewrts: %d (%d%%) reloc.: %d (%d%%)", |
duke@435 | 2529 | _nof_invocations, |
duke@435 | 2530 | _nof_rewrites, (_nof_rewrites * 100) / _nof_invocations, |
duke@435 | 2531 | _nof_relocations, (_nof_relocations * 100) / _nof_invocations); |
duke@435 | 2532 | } |
duke@435 | 2533 | } |
duke@435 | 2534 | #endif |
duke@435 | 2535 | return methodHandle(THREAD, method()); |
duke@435 | 2536 | } |