generateOopMap.cpp revision 342:37f87013dfd8
1148330Snetchild/* 2148330Snetchild * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. 3148330Snetchild * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4148330Snetchild * 5148330Snetchild * This code is free software; you can redistribute it and/or modify it 6148330Snetchild * under the terms of the GNU General Public License version 2 only, as 7148330Snetchild * published by the Free Software Foundation. 8148330Snetchild * 9148330Snetchild * This code is distributed in the hope that it will be useful, but WITHOUT 10148330Snetchild * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11148330Snetchild * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12148330Snetchild * version 2 for more details (a copy is included in the LICENSE file that 13148330Snetchild * accompanied this code). 14148543Snetchild * 15148543Snetchild * You should have received a copy of the GNU General Public License version 16148330Snetchild * 2 along with this work; if not, write to the Free Software Foundation, 17160983Sbrooks * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18160983Sbrooks * 19158687Sphk * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20158687Sphk * CA 95054 USA or visit www.sun.com if you need additional information or 21158687Sphk * have any questions. 22158687Sphk * 23158687Sphk */ 24158687Sphk 25158687Sphk// 26158687Sphk// 27158687Sphk// Compute stack layouts for each instruction in method. 28158687Sphk// 29158687Sphk// Problems: 30158687Sphk// - What to do about jsr with different types of local vars? 31158687Sphk// Need maps that are conditional on jsr path? 32158687Sphk// - Jsr and exceptions should be done more efficiently (the retAddr stuff) 33158687Sphk// 34158687Sphk// Alternative: 35158687Sphk// - Could extend verifier to provide this information. 36158687Sphk// For: one fewer abstract interpreter to maintain. Against: the verifier 37158687Sphk// solves a bigger problem so slower (undesirable to force verification of 38158687Sphk// everything?). 39158687Sphk// 40158687Sphk// Algorithm: 41158687Sphk// Partition bytecodes into basic blocks 42158687Sphk// For each basic block: store entry state (vars, stack). For instructions 43158687Sphk// inside basic blocks we do not store any state (instead we recompute it 44158687Sphk// from state produced by previous instruction). 45158687Sphk// 46158687Sphk// Perform abstract interpretation of bytecodes over this lattice: 47158687Sphk// 48158687Sphk// _--'#'--_ 49158687Sphk// / / \ \ 50158687Sphk// / / \ \ 51158687Sphk// / | | \ 52158687Sphk// 'r' 'v' 'p' ' ' 53158687Sphk// \ | | / 54158687Sphk// \ \ / / 55158687Sphk// \ \ / / 56158687Sphk// -- '@' -- 57158687Sphk// 58158687Sphk// '#' top, result of conflict merge 59158687Sphk// 'r' reference type 60158687Sphk// 'v' value type 61158687Sphk// 'p' pc type for jsr/ret 62158687Sphk// ' ' uninitialized; never occurs on operand stack in Java 63158687Sphk// '@' bottom/unexecuted; initial state each bytecode. 64158687Sphk// 65158687Sphk// Basic block headers are the only merge points. We use this iteration to 66158687Sphk// compute the information: 67158687Sphk// 68158687Sphk// find basic blocks; 69158687Sphk// initialize them with uninitialized state; 70158687Sphk// initialize first BB according to method signature; 71158687Sphk// mark first BB changed 72158618Smaxim// while (some BB is changed) do { 73158618Smaxim// perform abstract interpration of all bytecodes in BB; 74158618Smaxim// merge exit state of BB into entry state of all successor BBs, 75158512Smlaier// noting if any of these change; 76158512Smlaier// } 77158512Smlaier// 78158512Smlaier// One additional complication is necessary. The jsr instruction pushes 79158512Smlaier// a return PC on the stack (a 'p' type in the abstract interpretation). 80158754Smarcel// To be able to process "ret" bytecodes, we keep track of these return 81158754Smarcel// PC's in a 'retAddrs' structure in abstract interpreter context (when 82157221Ssimon// processing a "ret" bytecodes, it is not sufficient to know that it gets 83157221Ssimon// an argument of the right type 'p'; we need to know which address it 84156676Sharti// returns to). 85156676Sharti// 86153662Sjhb// (Note this comment is borrowed form the original author of the algorithm) 87153662Sjhb 88153430Siedowse#include "incls/_precompiled.incl" 89153430Siedowse#include "incls/_generateOopMap.cpp.incl" 90153430Siedowse 91153430Siedowse// ComputeCallStack 92153430Siedowse// 93151845Syar// Specialization of SignatureIterator - compute the effects of a call 94151845Syar// 95151271Spjdclass ComputeCallStack : public SignatureIterator { 96151271Spjd CellTypeState *_effect; 97150676Smlaier int _idx; 98150677Smlaier 99150002Snetchild void setup(); 100150002Snetchild void set(CellTypeState state) { _effect[_idx++] = state; } 101150002Snetchild int length() { return _idx; }; 102150002Snetchild 103149454Sglebius virtual void do_bool () { set(CellTypeState::value); }; 104148808Sru virtual void do_char () { set(CellTypeState::value); }; 105148808Sru virtual void do_float () { set(CellTypeState::value); }; 106148825Snetchild virtual void do_byte () { set(CellTypeState::value); }; 107148825Snetchild virtual void do_short () { set(CellTypeState::value); }; 108148356Sdougb virtual void do_int () { set(CellTypeState::value); }; 109148356Sdougb virtual void do_void () { set(CellTypeState::bottom);}; 110148572Snetchild virtual void do_object(int begin, int end) { set(CellTypeState::ref); }; 111148330Snetchild virtual void do_array (int begin, int end) { set(CellTypeState::ref); }; 112148330Snetchild 113148330Snetchild void do_double() { set(CellTypeState::value); 114148330Snetchild set(CellTypeState::value); } 115148572Snetchild void do_long () { set(CellTypeState::value); 116148572Snetchild set(CellTypeState::value); } 117149105Simp 118148572Snetchildpublic: 119148572Snetchild ComputeCallStack(symbolOop signature) : SignatureIterator(signature) {}; 120148572Snetchild 121148572Snetchild // Compute methods 122148572Snetchild int compute_for_parameters(bool is_static, CellTypeState *effect) { 123148572Snetchild _idx = 0; 124148572Snetchild _effect = effect; 125148572Snetchild 126148572Snetchild if (!is_static) 127148572Snetchild effect[_idx++] = CellTypeState::ref; 128148572Snetchild 129148572Snetchild iterate_parameters(); 130148572Snetchild 131148572Snetchild return length(); 132153939Snetchild }; 133153939Snetchild 134153939Snetchild int compute_for_returntype(CellTypeState *effect) { 135153939Snetchild _idx = 0; 136148330Snetchild _effect = effect; 137148330Snetchild iterate_returntype(); 138148423Sdougb set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works 139148423Sdougb 140148330Snetchild return length(); 141148330Snetchild } 142148330Snetchild}; 143148330Snetchild 144148572Snetchild//========================================================================================= 145148572Snetchild// ComputeEntryStack 146148353Sdougb// 147148353Sdougb// Specialization of SignatureIterator - in order to set up first stack frame 148149105Simp// 149149105Simpclass ComputeEntryStack : public SignatureIterator { 150148572Snetchild CellTypeState *_effect; 151148572Snetchild int _idx; 152149105Simp 153148572Snetchild void setup(); 154155813Snetchild void set(CellTypeState state) { _effect[_idx++] = state; } 155155813Snetchild int length() { return _idx; }; 156155813Snetchild 157155813Snetchild virtual void do_bool () { set(CellTypeState::value); }; 158148330Snetchild virtual void do_char () { set(CellTypeState::value); }; 159148330Snetchild virtual void do_float () { set(CellTypeState::value); }; 160148330Snetchild virtual void do_byte () { set(CellTypeState::value); }; 161148330Snetchild virtual void do_short () { set(CellTypeState::value); }; 162148330Snetchild virtual void do_int () { set(CellTypeState::value); }; 163148330Snetchild virtual void do_void () { set(CellTypeState::bottom);}; 164148330Snetchild virtual void do_object(int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } 165155813Snetchild virtual void do_array (int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } 166148330Snetchild 167148330Snetchild void do_double() { set(CellTypeState::value); 168148330Snetchild set(CellTypeState::value); } 169148330Snetchild void do_long () { set(CellTypeState::value); 170148330Snetchild set(CellTypeState::value); } 171148330Snetchild 172148543Snetchildpublic: 173148543Snetchild ComputeEntryStack(symbolOop signature) : SignatureIterator(signature) {}; 174148543Snetchild 175148543Snetchild // Compute methods 176148543Snetchild int compute_for_parameters(bool is_static, CellTypeState *effect) { 177148543Snetchild _idx = 0; 178148543Snetchild _effect = effect; 179148543Snetchild 180148543Snetchild if (!is_static) 181148543Snetchild effect[_idx++] = CellTypeState::make_slot_ref(0); 182148543Snetchild 183148543Snetchild iterate_parameters(); 184148543Snetchild 185148543Snetchild return length(); 186148543Snetchild }; 187148543Snetchild 188148543Snetchild int compute_for_returntype(CellTypeState *effect) { 189148543Snetchild _idx = 0; 190148543Snetchild _effect = effect; 191148543Snetchild iterate_returntype(); 192148543Snetchild set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works 193148572Snetchild 194148572Snetchild return length(); 195148572Snetchild } 196148572Snetchild}; 197148572Snetchild 198148572Snetchild//===================================================================================== 199148572Snetchild// 200148572Snetchild// Implementation of RetTable/RetTableEntry 201148572Snetchild// 202148572Snetchild// Contains function to itereate through all bytecodes 203148572Snetchild// and find all return entry points 204148572Snetchild// 205148572Snetchildint RetTable::_init_nof_entries = 10; 206148572Snetchildint RetTableEntry::_init_nof_jsrs = 5; 207148572Snetchild 208148572Snetchildvoid RetTableEntry::add_delta(int bci, int delta) { 209148572Snetchild if (_target_bci > bci) _target_bci += delta; 210148572Snetchild 211148572Snetchild for (int k = 0; k < _jsrs->length(); k++) { 212148572Snetchild int jsr = _jsrs->at(k); 213148572Snetchild if (jsr > bci) _jsrs->at_put(k, jsr+delta); 214148572Snetchild } 215148572Snetchild} 216148572Snetchild 217148572Snetchildvoid RetTable::compute_ret_table(methodHandle method) { 218148572Snetchild BytecodeStream i(method); 219148572Snetchild Bytecodes::Code bytecode; 220148572Snetchild 221148572Snetchild while( (bytecode = i.next()) >= 0) { 222148572Snetchild switch (bytecode) { 223148572Snetchild case Bytecodes::_jsr: 224148572Snetchild add_jsr(i.next_bci(), i.dest()); 225148572Snetchild break; 226148572Snetchild case Bytecodes::_jsr_w: 227148572Snetchild add_jsr(i.next_bci(), i.dest_w()); 228148572Snetchild break; 229148572Snetchild } 230148572Snetchild } 231148572Snetchild} 232148572Snetchild 233148572Snetchildvoid RetTable::add_jsr(int return_bci, int target_bci) { 234148572Snetchild RetTableEntry* entry = _first; 235148572Snetchild 236148572Snetchild // Scan table for entry 237148572Snetchild for (;entry && entry->target_bci() != target_bci; entry = entry->next()); 238148572Snetchild 239148572Snetchild if (!entry) { 240148572Snetchild // Allocate new entry and put in list 241148572Snetchild entry = new RetTableEntry(target_bci, _first); 242148572Snetchild _first = entry; 243148572Snetchild } 244148572Snetchild 245148572Snetchild // Now "entry" is set. Make sure that the entry is initialized 246148572Snetchild // and has room for the new jsr. 247148572Snetchild entry->add_jsr(return_bci); 248148572Snetchild} 249148572Snetchild 250148572SnetchildRetTableEntry* RetTable::find_jsrs_for_target(int targBci) { 251148572Snetchild RetTableEntry *cur = _first; 252148572Snetchild 253148572Snetchild while(cur) { 254148572Snetchild assert(cur->target_bci() != -1, "sanity check"); 255148572Snetchild if (cur->target_bci() == targBci) return cur; 256148572Snetchild cur = cur->next(); 257148572Snetchild } 258148572Snetchild ShouldNotReachHere(); 259148572Snetchild return NULL; 260148572Snetchild} 261148572Snetchild 262148572Snetchild// The instruction at bci is changing size by "delta". Update the return map. 263148572Snetchildvoid RetTable::update_ret_table(int bci, int delta) { 264148572Snetchild RetTableEntry *cur = _first; 265148572Snetchild while(cur) { 266148572Snetchild cur->add_delta(bci, delta); 267148572Snetchild cur = cur->next(); 268148572Snetchild } 269148572Snetchild} 270148572Snetchild 271148572Snetchild// 272148572Snetchild// Celltype state 273148572Snetchild// 274148572Snetchild 275148572SnetchildCellTypeState CellTypeState::bottom = CellTypeState::make_bottom(); 276148572SnetchildCellTypeState CellTypeState::uninit = CellTypeState::make_any(uninit_value); 277148572SnetchildCellTypeState CellTypeState::ref = CellTypeState::make_any(ref_conflict); 278148572SnetchildCellTypeState CellTypeState::value = CellTypeState::make_any(val_value); 279148572SnetchildCellTypeState CellTypeState::refUninit = CellTypeState::make_any(ref_conflict | uninit_value); 280148572SnetchildCellTypeState CellTypeState::top = CellTypeState::make_top(); 281148572SnetchildCellTypeState CellTypeState::addr = CellTypeState::make_any(addr_conflict); 282148572Snetchild 283148572Snetchild// Commonly used constants 284148572Snetchildstatic CellTypeState epsilonCTS[1] = { CellTypeState::bottom }; 285148572Snetchildstatic CellTypeState refCTS = CellTypeState::ref; 286148572Snetchildstatic CellTypeState valCTS = CellTypeState::value; 287148572Snetchildstatic CellTypeState vCTS[2] = { CellTypeState::value, CellTypeState::bottom }; 288148572Snetchildstatic CellTypeState rCTS[2] = { CellTypeState::ref, CellTypeState::bottom }; 289148572Snetchildstatic CellTypeState rrCTS[3] = { CellTypeState::ref, CellTypeState::ref, CellTypeState::bottom }; 290148572Snetchildstatic CellTypeState vrCTS[3] = { CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; 291148572Snetchildstatic CellTypeState vvCTS[3] = { CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; 292148572Snetchildstatic CellTypeState rvrCTS[4] = { CellTypeState::ref, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; 293148572Snetchildstatic CellTypeState vvrCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; 294148572Snetchildstatic CellTypeState vvvCTS[4] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; 295148572Snetchildstatic CellTypeState vvvrCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::ref, CellTypeState::bottom }; 296148572Snetchildstatic CellTypeState vvvvCTS[5] = { CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::value, CellTypeState::bottom }; 297148572Snetchild 298148572Snetchildchar CellTypeState::to_char() const { 299148572Snetchild if (can_be_reference()) { 300148572Snetchild if (can_be_value() || can_be_address()) 301148330Snetchild return '#'; // Conflict that needs to be rewritten 302148330Snetchild else 303148330Snetchild return 'r'; 304148330Snetchild } else if (can_be_value()) 305148330Snetchild return 'v'; 306148572Snetchild else if (can_be_address()) 307148572Snetchild return 'p'; 308148572Snetchild else if (can_be_uninit()) 309148572Snetchild return ' '; 310148572Snetchild else 311148572Snetchild return '@'; 312148572Snetchild} 313148572Snetchild 314148572Snetchild 315148572Snetchild// Print a detailed CellTypeState. Indicate all bits that are set. If 316149113Simp// the CellTypeState represents an address or a reference, print the 317149113Simp// value of the additional information. 318149113Simpvoid CellTypeState::print(outputStream *os) { 319149113Simp if (can_be_address()) { 320149113Simp os->print("(p"); 321149113Simp } else { 322149113Simp os->print("( "); 323148572Snetchild } 324148572Snetchild if (can_be_reference()) { 325148572Snetchild os->print("r"); 326148572Snetchild } else { 327148572Snetchild os->print(" "); 328149105Simp } 329148572Snetchild if (can_be_value()) { 330148572Snetchild os->print("v"); 331148572Snetchild } else { 332148572Snetchild os->print(" "); 333148572Snetchild } 334148572Snetchild if (can_be_uninit()) { 335148572Snetchild os->print("u|"); 336148572Snetchild } else { 337148683Sru os->print(" |"); 338148330Snetchild } 339148330Snetchild if (is_info_top()) { 340148330Snetchild os->print("Top)"); 341148330Snetchild } else if (is_info_bottom()) { 342156385Syar os->print("Bot)"); 343156385Syar } else { 344148330Snetchild if (is_reference()) { 345148330Snetchild int info = get_info(); 346148330Snetchild int data = info & ~(ref_not_lock_bit | ref_slot_bit); 347148330Snetchild if (info & ref_not_lock_bit) { 348148330Snetchild // Not a monitor lock reference. 349148330Snetchild if (info & ref_slot_bit) { 350148330Snetchild // slot 351148330Snetchild os->print("slot%d)", data); 352148330Snetchild } else { 353148330Snetchild // line 354148330Snetchild os->print("line%d)", data); 355148330Snetchild } 356148330Snetchild } else { 357148330Snetchild // lock 358148330Snetchild os->print("lock%d)", data); 359148330Snetchild } 360148330Snetchild } else { 361148330Snetchild os->print("%d)", get_info()); 362148330Snetchild } 363148330Snetchild } 364148330Snetchild} 365148572Snetchild 366148572Snetchild// 367149105Simp// Basicblock handling methods 368148572Snetchild// 369148572Snetchild 370148572Snetchildvoid GenerateOopMap ::initialize_bb() { 371148572Snetchild _gc_points = 0; 372148572Snetchild _bb_count = 0; 373148572Snetchild _bb_hdr_bits.clear(); 374148572Snetchild _bb_hdr_bits.resize(method()->code_size()); 375155279Savatar} 376155279Savatar 377155279Savatarvoid GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) { 378155279Savatar assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds"); 379148572Snetchild if (c->is_bb_header(bci)) 380148572Snetchild return; 381148572Snetchild 382148330Snetchild if (TraceNewOopMapGeneration) { 383148330Snetchild tty->print_cr("Basicblock#%d begins at: %d", c->_bb_count, bci); 384148330Snetchild } 385148330Snetchild c->set_bbmark_bit(bci); 386148330Snetchild c->_bb_count++; 387148330Snetchild} 388148330Snetchild 389148330Snetchild 390148330Snetchildvoid GenerateOopMap::mark_bbheaders_and_count_gc_points() { 391148330Snetchild initialize_bb(); 392148330Snetchild 393148330Snetchild bool fellThrough = false; // False to get first BB marked. 394148330Snetchild 395148330Snetchild // First mark all exception handlers as start of a basic-block 396148330Snetchild typeArrayOop excps = method()->exception_table(); 397148330Snetchild for(int i = 0; i < excps->length(); i += 4) { 398149105Simp int handler_pc_idx = i+2; 399149105Simp bb_mark_fct(this, excps->int_at(handler_pc_idx), NULL); 400148572Snetchild } 401148572Snetchild 402148572Snetchild // Then iterate through the code 403148572Snetchild BytecodeStream bcs(_method); 404148330Snetchild Bytecodes::Code bytecode; 405148330Snetchild 406148330Snetchild while( (bytecode = bcs.next()) >= 0) { 407148330Snetchild int bci = bcs.bci(); 408148330Snetchild 409148330Snetchild if (!fellThrough) 410148330Snetchild bb_mark_fct(this, bci, NULL); 411148330Snetchild 412148330Snetchild fellThrough = jump_targets_do(&bcs, &GenerateOopMap::bb_mark_fct, NULL); 413148330Snetchild 414148330Snetchild /* We will also mark successors of jsr's as basic block headers. */ 415148330Snetchild switch (bytecode) { 416148330Snetchild case Bytecodes::_jsr: 417148330Snetchild assert(!fellThrough, "should not happen"); 418148330Snetchild bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL); 419148330Snetchild break; 420148330Snetchild case Bytecodes::_jsr_w: 421148330Snetchild assert(!fellThrough, "should not happen"); 422148330Snetchild bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL); 423148330Snetchild break; 424148330Snetchild } 425148330Snetchild 426148330Snetchild if (possible_gc_point(&bcs)) 427148572Snetchild _gc_points++; 428148572Snetchild } 429148572Snetchild} 430148572Snetchild 431148572Snetchildvoid GenerateOopMap::reachable_basicblock(GenerateOopMap *c, int bci, int *data) { 432148572Snetchild assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds"); 433148572Snetchild BasicBlock* bb = c->get_basic_block_at(bci); 434148572Snetchild if (bb->is_dead()) { 435148572Snetchild bb->mark_as_alive(); 436148572Snetchild *data = 1; // Mark basicblock as changed 437148572Snetchild } 438148572Snetchild} 439148572Snetchild 440148572Snetchild 441148572Snetchildvoid GenerateOopMap::mark_reachable_code() { 442148572Snetchild int change = 1; // int to get function pointers to work 443148572Snetchild 444148572Snetchild // Mark entry basic block as alive and all exception handlers 445148572Snetchild _basic_blocks[0].mark_as_alive(); 446148572Snetchild typeArrayOop excps = method()->exception_table(); 447148572Snetchild for(int i = 0; i < excps->length(); i += 4) { 448148572Snetchild int handler_pc_idx = i+2; 449148572Snetchild BasicBlock *bb = get_basic_block_at(excps->int_at(handler_pc_idx)); 450148572Snetchild // If block is not already alive (due to multiple exception handlers to same bb), then 451148572Snetchild // make it alive 452148572Snetchild if (bb->is_dead()) bb->mark_as_alive(); 453148572Snetchild } 454148572Snetchild 455148572Snetchild BytecodeStream bcs(_method); 456148572Snetchild 457148572Snetchild // Iterate through all basic blocks until we reach a fixpoint 458148572Snetchild while (change) { 459148572Snetchild change = 0; 460148572Snetchild 461148572Snetchild for (int i = 0; i < _bb_count; i++) { 462148572Snetchild BasicBlock *bb = &_basic_blocks[i]; 463148572Snetchild if (bb->is_alive()) { 464148572Snetchild // Position bytecodestream at last bytecode in basicblock 465148572Snetchild bcs.set_start(bb->_end_bci); 466148572Snetchild bcs.next(); 467148572Snetchild Bytecodes::Code bytecode = bcs.code(); 468148572Snetchild int bci = bcs.bci(); 469148572Snetchild assert(bci == bb->_end_bci, "wrong bci"); 470148572Snetchild 471148572Snetchild bool fell_through = jump_targets_do(&bcs, &GenerateOopMap::reachable_basicblock, &change); 472148572Snetchild 473148572Snetchild // We will also mark successors of jsr's as alive. 474148572Snetchild switch (bytecode) { 475148572Snetchild case Bytecodes::_jsr: 476148572Snetchild case Bytecodes::_jsr_w: 477148572Snetchild assert(!fell_through, "should not happen"); 478148572Snetchild reachable_basicblock(this, bci + Bytecodes::length_for(bytecode), &change); 479148572Snetchild break; 480148572Snetchild } 481148572Snetchild if (fell_through) { 482148572Snetchild // Mark successor as alive 483148572Snetchild if (bb[1].is_dead()) { 484148572Snetchild bb[1].mark_as_alive(); 485148572Snetchild change = 1; 486148572Snetchild } 487148572Snetchild } 488148572Snetchild } 489148572Snetchild } 490148572Snetchild } 491148572Snetchild} 492148572Snetchild 493148572Snetchild/* If the current instruction in "c" has no effect on control flow, 494148572Snetchild returns "true". Otherwise, calls "jmpFct" one or more times, with 495148572Snetchild "c", an appropriate "pcDelta", and "data" as arguments, then 496148572Snetchild returns "false". There is one exception: if the current 497148572Snetchild instruction is a "ret", returns "false" without calling "jmpFct". 498148572Snetchild Arrangements for tracking the control flow of a "ret" must be made 499148572Snetchild externally. */ 500148572Snetchildbool GenerateOopMap::jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int *data) { 501148572Snetchild int bci = bcs->bci(); 502148572Snetchild 503148572Snetchild switch (bcs->code()) { 504148572Snetchild case Bytecodes::_ifeq: 505148572Snetchild case Bytecodes::_ifne: 506148572Snetchild case Bytecodes::_iflt: 507148572Snetchild case Bytecodes::_ifge: 508148572Snetchild case Bytecodes::_ifgt: 509148572Snetchild case Bytecodes::_ifle: 510148572Snetchild case Bytecodes::_if_icmpeq: 511148572Snetchild case Bytecodes::_if_icmpne: 512148572Snetchild case Bytecodes::_if_icmplt: 513148572Snetchild case Bytecodes::_if_icmpge: 514148572Snetchild case Bytecodes::_if_icmpgt: 515148572Snetchild case Bytecodes::_if_icmple: 516148572Snetchild case Bytecodes::_if_acmpeq: 517148572Snetchild case Bytecodes::_if_acmpne: 518148572Snetchild case Bytecodes::_ifnull: 519148572Snetchild case Bytecodes::_ifnonnull: 520148572Snetchild (*jmpFct)(this, bcs->dest(), data); 521148572Snetchild (*jmpFct)(this, bci + 3, data); 522148572Snetchild break; 523148572Snetchild 524148572Snetchild case Bytecodes::_goto: 525148572Snetchild (*jmpFct)(this, bcs->dest(), data); 526149105Simp break; 527149105Simp case Bytecodes::_goto_w: 528149105Simp (*jmpFct)(this, bcs->dest_w(), data); 529149105Simp break; 530148572Snetchild case Bytecodes::_tableswitch: 531148572Snetchild { Bytecode_tableswitch *tableswitch = Bytecode_tableswitch_at(bcs->bcp()); 532148572Snetchild int len = tableswitch->length(); 533148572Snetchild 534148572Snetchild (*jmpFct)(this, bci + tableswitch->default_offset(), data); /* Default. jump address */ 535148572Snetchild while (--len >= 0) { 536148572Snetchild (*jmpFct)(this, bci + tableswitch->dest_offset_at(len), data); 537148572Snetchild } 538148572Snetchild break; 539148572Snetchild } 540148572Snetchild 541148572Snetchild case Bytecodes::_lookupswitch: 542148572Snetchild { Bytecode_lookupswitch *lookupswitch = Bytecode_lookupswitch_at(bcs->bcp()); 543148572Snetchild int npairs = lookupswitch->number_of_pairs(); 544148572Snetchild (*jmpFct)(this, bci + lookupswitch->default_offset(), data); /* Default. */ 545148572Snetchild while(--npairs >= 0) { 546148572Snetchild LookupswitchPair *pair = lookupswitch->pair_at(npairs); 547148572Snetchild (*jmpFct)(this, bci + pair->offset(), data); 548148572Snetchild } 549148572Snetchild break; 550148572Snetchild } 551148572Snetchild case Bytecodes::_jsr: 552148572Snetchild assert(bcs->is_wide()==false, "sanity check"); 553148572Snetchild (*jmpFct)(this, bcs->dest(), data); 554148572Snetchild 555148572Snetchild 556148572Snetchild 557148572Snetchild break; 558148572Snetchild case Bytecodes::_jsr_w: 559148572Snetchild (*jmpFct)(this, bcs->dest_w(), data); 560148572Snetchild break; 561148572Snetchild case Bytecodes::_wide: 562148572Snetchild ShouldNotReachHere(); 563148572Snetchild return true; 564148572Snetchild break; 565148572Snetchild case Bytecodes::_athrow: 566148572Snetchild case Bytecodes::_ireturn: 567148572Snetchild case Bytecodes::_lreturn: 568148572Snetchild case Bytecodes::_freturn: 569148572Snetchild case Bytecodes::_dreturn: 570148572Snetchild case Bytecodes::_areturn: 571148572Snetchild case Bytecodes::_return: 572148572Snetchild case Bytecodes::_ret: 573148572Snetchild break; 574148572Snetchild default: 575148572Snetchild return true; 576148572Snetchild } 577148572Snetchild return false; 578148572Snetchild} 579148572Snetchild 580148572Snetchild/* Requires "pc" to be the head of a basic block; returns that basic 581148572Snetchild block. */ 582148572SnetchildBasicBlock *GenerateOopMap::get_basic_block_at(int bci) const { 583148572Snetchild BasicBlock* bb = get_basic_block_containing(bci); 584148572Snetchild assert(bb->_bci == bci, "should have found BB"); 585148572Snetchild return bb; 586148572Snetchild} 587148572Snetchild 588148572Snetchild// Requires "pc" to be the start of an instruction; returns the basic 589149105Simp// block containing that instruction. */ 590149105SimpBasicBlock *GenerateOopMap::get_basic_block_containing(int bci) const { 591149105Simp BasicBlock *bbs = _basic_blocks; 592149105Simp int lo = 0, hi = _bb_count - 1; 593149105Simp 594149105Simp while (lo <= hi) { 595149105Simp int m = (lo + hi) / 2; 596149105Simp int mbci = bbs[m]._bci; 597148572Snetchild int nbci; 598148572Snetchild 599160165Savatar if ( m == _bb_count-1) { 600160165Savatar assert( bci >= mbci && bci < method()->code_size(), "sanity check failed"); 601148330Snetchild return bbs+m; 602148330Snetchild } else { 603148330Snetchild nbci = bbs[m+1]._bci; 604149105Simp } 605149105Simp 606149105Simp if ( mbci <= bci && bci < nbci) { 607149105Simp return bbs+m; 608149105Simp } else if (mbci < bci) { 609149105Simp lo = m + 1; 610149105Simp } else { 611149105Simp assert(mbci > bci, "sanity check"); 612149105Simp hi = m - 1; 613149105Simp } 614149105Simp } 615149105Simp 616149105Simp fatal("should have found BB"); 617149105Simp return NULL; 618149105Simp} 619149105Simp 620149105Simpvoid GenerateOopMap::restore_state(BasicBlock *bb) 621149105Simp{ 622149105Simp memcpy(_state, bb->_state, _state_len*sizeof(CellTypeState)); 623149105Simp _stack_top = bb->_stack_top; 624149105Simp _monitor_top = bb->_monitor_top; 625149105Simp} 626149105Simp 627149105Simpint GenerateOopMap::next_bb_start_pc(BasicBlock *bb) { 628149105Simp int bbNum = bb - _basic_blocks + 1; 629160165Savatar if (bbNum == _bb_count) 630160165Savatar return method()->code_size(); 631160165Savatar 632148330Snetchild return _basic_blocks[bbNum]._bci; 633148330Snetchild} 634148330Snetchild 635148330Snetchild// 636148330Snetchild// CellType handling methods 637148330Snetchild// 638148330Snetchild 639148330Snetchildvoid GenerateOopMap::init_state() { 640149105Simp _state_len = _max_locals + _max_stack + _max_monitors; 641149105Simp _state = NEW_RESOURCE_ARRAY(CellTypeState, _state_len); 642149105Simp memset(_state, 0, _state_len * sizeof(CellTypeState)); 643149105Simp _state_vec_buf = NEW_RESOURCE_ARRAY(char, MAX3(_max_locals, _max_stack, _max_monitors) + 1/*for null terminator char */); 644149105Simp} 645148330Snetchild 646149105Simpvoid GenerateOopMap::make_context_uninitialized() { 647149105Simp CellTypeState* vs = vars(); 648149105Simp 649149105Simp for (int i = 0; i < _max_locals; i++) 650149105Simp vs[i] = CellTypeState::uninit; 651149105Simp 652149105Simp _stack_top = 0; 653149105Simp _monitor_top = 0; 654149105Simp} 655149105Simp 656149105Simpint GenerateOopMap::methodsig_to_effect(symbolOop signature, bool is_static, CellTypeState* effect) { 657149105Simp ComputeEntryStack ces(signature); 658149105Simp return ces.compute_for_parameters(is_static, effect); 659160165Savatar} 660160165Savatar 661160165Savatar// Return result of merging cts1 and cts2. 662148330SnetchildCellTypeState CellTypeState::merge(CellTypeState cts, int slot) const { 663148330Snetchild CellTypeState result; 664148330Snetchild 665148330Snetchild assert(!is_bottom() && !cts.is_bottom(), 666149105Simp "merge of bottom values is handled elsewhere"); 667149105Simp 668149105Simp result._state = _state | cts._state; 669148330Snetchild 670148330Snetchild // If the top bit is set, we don't need to do any more work. 671148330Snetchild if (!result.is_info_top()) { 672148330Snetchild assert((result.can_be_address() || result.can_be_reference()), 673148330Snetchild "only addresses and references have non-top info"); 674148330Snetchild 675148330Snetchild if (!equal(cts)) { 676148330Snetchild // The two values being merged are different. Raise to top. 677148330Snetchild if (result.is_reference()) { 678148330Snetchild result = CellTypeState::make_slot_ref(slot); 679148330Snetchild } else { 680148330Snetchild result._state |= info_conflict; 681148330Snetchild } 682148330Snetchild } 683148330Snetchild } 684148330Snetchild assert(result.is_valid_state(), "checking that CTS merge maintains legal state"); 685148543Snetchild 686149113Simp return result; 687149113Simp} 688149113Simp 689149113Simp// Merge the variable state for locals and stack from cts into bbts. 690149113Simpbool GenerateOopMap::merge_local_state_vectors(CellTypeState* cts, 691149113Simp CellTypeState* bbts) { 692149113Simp int i; 693149113Simp int len = _max_locals + _stack_top; 694149113Simp bool change = false; 695149113Simp 696149113Simp for (i = len - 1; i >= 0; i--) { 697148330Snetchild CellTypeState v = cts[i].merge(bbts[i], i); 698148330Snetchild change = change || !v.equal(bbts[i]); 699149113Simp bbts[i] = v; 700149113Simp } 701149113Simp 702149113Simp return change; 703149113Simp} 704149113Simp 705149113Simp// Merge the monitor stack state from cts into bbts. 706149113Simpbool GenerateOopMap::merge_monitor_state_vectors(CellTypeState* cts, 707149113Simp CellTypeState* bbts) { 708149113Simp bool change = false; 709149113Simp if (_max_monitors > 0 && _monitor_top != bad_monitors) { 710149113Simp // If there are no monitors in the program, or there has been 711149113Simp // a monitor matching error before this point in the program, 712149113Simp // then we do not merge in the monitor state. 713149113Simp 714149113Simp int base = _max_locals + _max_stack; 715149113Simp int len = base + _monitor_top; 716149113Simp for (int i = len - 1; i >= base; i--) { 717149113Simp CellTypeState v = cts[i].merge(bbts[i], i); 718149113Simp 719149113Simp // Can we prove that, when there has been a change, it will already 720149113Simp // have been detected at this point? That would make this equal 721149113Simp // check here unnecessary. 722149113Simp change = change || !v.equal(bbts[i]); 723149113Simp bbts[i] = v; 724149113Simp } 725149113Simp } 726149113Simp 727149113Simp return change; 728149113Simp} 729149113Simp 730149113Simpvoid GenerateOopMap::copy_state(CellTypeState *dst, CellTypeState *src) { 731148330Snetchild int len = _max_locals + _stack_top; 732148330Snetchild for (int i = 0; i < len; i++) { 733148330Snetchild if (src[i].is_nonlock_reference()) { 734148330Snetchild dst[i] = CellTypeState::make_slot_ref(i); 735148330Snetchild } else { 736148330Snetchild dst[i] = src[i]; 737148330Snetchild } 738151378Snetchild } 739151378Snetchild if (_max_monitors > 0 && _monitor_top != bad_monitors) { 740151378Snetchild int base = _max_locals + _max_stack; 741151378Snetchild len = base + _monitor_top; 742151378Snetchild for (int i = base; i < len; i++) { 743151378Snetchild dst[i] = src[i]; 744151378Snetchild } 745151378Snetchild } 746151378Snetchild} 747151378Snetchild 748151378Snetchild 749151378Snetchild// Merge the states for the current block and the next. As long as a 750151378Snetchild// block is reachable the locals and stack must be merged. If the 751151378Snetchild// stack heights don't match then this is a verification error and 752151378Snetchild// it's impossible to interpret the code. Simultaneously monitor 753151378Snetchild// states are being check to see if they nest statically. If monitor 754151378Snetchild// depths match up then their states are merged. Otherwise the 755151378Snetchild// mismatch is simply recorded and interpretation continues since 756151378Snetchild// monitor matching is purely informational and doesn't say anything 757151378Snetchild// about the correctness of the code. 758151378Snetchildvoid GenerateOopMap::merge_state_into_bb(BasicBlock *bb) { 759151378Snetchild assert(bb->is_alive(), "merging state into a dead basicblock"); 760151378Snetchild 761151378Snetchild if (_stack_top == bb->_stack_top) { 762151378Snetchild // always merge local state even if monitors don't match. 763151378Snetchild if (merge_local_state_vectors(_state, bb->_state)) { 764151378Snetchild bb->set_changed(true); 765151378Snetchild } 766151378Snetchild if (_monitor_top == bb->_monitor_top) { 767151378Snetchild // monitors still match so continue merging monitor states. 768151378Snetchild if (merge_monitor_state_vectors(_state, bb->_state)) { 769151378Snetchild bb->set_changed(true); 770151378Snetchild } 771151378Snetchild } else { 772151378Snetchild if (TraceMonitorMismatch) { 773151378Snetchild report_monitor_mismatch("monitor stack height merge conflict"); 774151378Snetchild } 775151378Snetchild // When the monitor stacks are not matched, we set _monitor_top to 776151378Snetchild // bad_monitors. This signals that, from here on, the monitor stack cannot 777151378Snetchild // be trusted. In particular, monitorexit bytecodes may throw 778151378Snetchild // exceptions. We mark this block as changed so that the change 779151378Snetchild // propagates properly. 780151378Snetchild bb->_monitor_top = bad_monitors; 781151378Snetchild bb->set_changed(true); 782151378Snetchild _monitor_safe = false; 783151378Snetchild } 784151378Snetchild } else if (!bb->is_reachable()) { 785151378Snetchild // First time we look at this BB 786151378Snetchild copy_state(bb->_state, _state); 787151378Snetchild bb->_stack_top = _stack_top; 788151378Snetchild bb->_monitor_top = _monitor_top; 789151378Snetchild bb->set_changed(true); 790151378Snetchild } else { 791151378Snetchild verify_error("stack height conflict: %d vs. %d", _stack_top, bb->_stack_top); 792151378Snetchild } 793151378Snetchild} 794151378Snetchild 795151378Snetchildvoid GenerateOopMap::merge_state(GenerateOopMap *gom, int bci, int* data) { 796151378Snetchild gom->merge_state_into_bb(gom->get_basic_block_at(bci)); 797151378Snetchild} 798151378Snetchild 799151378Snetchildvoid GenerateOopMap::set_var(int localNo, CellTypeState cts) { 800151378Snetchild assert(cts.is_reference() || cts.is_value() || cts.is_address(), 801151378Snetchild "wrong celltypestate"); 802151378Snetchild if (localNo < 0 || localNo > _max_locals) { 803151378Snetchild verify_error("variable write error: r%d", localNo); 804151378Snetchild return; 805151378Snetchild } 806151378Snetchild vars()[localNo] = cts; 807151378Snetchild} 808151378Snetchild 809151378SnetchildCellTypeState GenerateOopMap::get_var(int localNo) { 810151378Snetchild assert(localNo < _max_locals + _nof_refval_conflicts, "variable read error") 811151378Snetchild if (localNo < 0 || localNo > _max_locals) { 812151378Snetchild verify_error("variable read error: r%d", localNo); 813151378Snetchild return valCTS; // just to pick something; 814151378Snetchild } 815151378Snetchild return vars()[localNo]; 816151378Snetchild} 817151378Snetchild 818151378SnetchildCellTypeState GenerateOopMap::pop() { 819151378Snetchild if ( _stack_top <= 0) { 820151378Snetchild verify_error("stack underflow"); 821151378Snetchild return valCTS; // just to pick something 822151378Snetchild } 823151378Snetchild return stack()[--_stack_top]; 824151378Snetchild} 825151378Snetchild 826151378Snetchildvoid GenerateOopMap::push(CellTypeState cts) { 827151378Snetchild if ( _stack_top >= _max_stack) { 828151378Snetchild verify_error("stack overflow"); 829151378Snetchild return; 830151378Snetchild } 831151378Snetchild stack()[_stack_top++] = cts; 832151378Snetchild} 833151378Snetchild 834151378SnetchildCellTypeState GenerateOopMap::monitor_pop() { 835151378Snetchild assert(_monitor_top != bad_monitors, "monitor_pop called on error monitor stack"); 836151378Snetchild if (_monitor_top == 0) { 837151378Snetchild // We have detected a pop of an empty monitor stack. 838151378Snetchild _monitor_safe = false; 839151378Snetchild _monitor_top = bad_monitors; 840151378Snetchild 841151378Snetchild if (TraceMonitorMismatch) { 842151378Snetchild report_monitor_mismatch("monitor stack underflow"); 843151378Snetchild } 844151378Snetchild return CellTypeState::ref; // just to keep the analysis going. 845151378Snetchild } 846151378Snetchild return monitors()[--_monitor_top]; 847151378Snetchild} 848151378Snetchild 849151378Snetchildvoid GenerateOopMap::monitor_push(CellTypeState cts) { 850151378Snetchild assert(_monitor_top != bad_monitors, "monitor_push called on error monitor stack"); 851151378Snetchild if (_monitor_top >= _max_monitors) { 852151378Snetchild // Some monitorenter is being executed more than once. 853151378Snetchild // This means that the monitor stack cannot be simulated. 854151378Snetchild _monitor_safe = false; 855151378Snetchild _monitor_top = bad_monitors; 856151378Snetchild 857151378Snetchild if (TraceMonitorMismatch) { 858151378Snetchild report_monitor_mismatch("monitor stack overflow"); 859151378Snetchild } 860151378Snetchild return; 861151378Snetchild } 862151378Snetchild monitors()[_monitor_top++] = cts; 863151378Snetchild} 864151378Snetchild 865151378Snetchild// 866151378Snetchild// Interpretation handling methods 867151378Snetchild// 868151378Snetchild 869151378Snetchildvoid GenerateOopMap::do_interpretation() 870151378Snetchild{ 871151378Snetchild // "i" is just for debugging, so we can detect cases where this loop is 872151378Snetchild // iterated more than once. 873151378Snetchild int i = 0; 874151378Snetchild do { 875151378Snetchild#ifndef PRODUCT 876151378Snetchild if (TraceNewOopMapGeneration) { 877151378Snetchild tty->print("\n\nIteration #%d of do_interpretation loop, method:\n", i); 878151378Snetchild method()->print_name(tty); 879151378Snetchild tty->print("\n\n"); 880151378Snetchild } 881151378Snetchild#endif 882151378Snetchild _conflict = false; 883151378Snetchild _monitor_safe = true; 884151378Snetchild // init_state is now called from init_basic_blocks. The length of a 885151378Snetchild // state vector cannot be determined until we have made a pass through 886151378Snetchild // the bytecodes counting the possible monitor entries. 887151378Snetchild if (!_got_error) init_basic_blocks(); 888151378Snetchild if (!_got_error) setup_method_entry_state(); 889151378Snetchild if (!_got_error) interp_all(); 890151378Snetchild if (!_got_error) rewrite_refval_conflicts(); 891151378Snetchild i++; 892151378Snetchild } while (_conflict && !_got_error); 893151378Snetchild} 894151378Snetchild 895151378Snetchildvoid GenerateOopMap::init_basic_blocks() { 896151378Snetchild // Note: Could consider reserving only the needed space for each BB's state 897151378Snetchild // (entry stack may not be of maximal height for every basic block). 898151378Snetchild // But cumbersome since we don't know the stack heights yet. (Nor the 899151378Snetchild // monitor stack heights...) 900151378Snetchild 901151378Snetchild _basic_blocks = NEW_RESOURCE_ARRAY(BasicBlock, _bb_count); 902151378Snetchild 903151378Snetchild // Make a pass through the bytecodes. Count the number of monitorenters. 904151378Snetchild // This can be used an upper bound on the monitor stack depth in programs 905151378Snetchild // which obey stack discipline with their monitor usage. Initialize the 906151378Snetchild // known information about basic blocks. 907151378Snetchild BytecodeStream j(_method); 908151378Snetchild Bytecodes::Code bytecode; 909151378Snetchild 910151378Snetchild int bbNo = 0; 911151378Snetchild int monitor_count = 0; 912151378Snetchild int prev_bci = -1; 913151378Snetchild while( (bytecode = j.next()) >= 0) { 914151378Snetchild if (j.code() == Bytecodes::_monitorenter) { 915151378Snetchild monitor_count++; 916151378Snetchild } 917151378Snetchild 918151378Snetchild int bci = j.bci(); 919151378Snetchild if (is_bb_header(bci)) { 920151378Snetchild // Initialize the basicblock structure 921151378Snetchild BasicBlock *bb = _basic_blocks + bbNo; 922151378Snetchild bb->_bci = bci; 923151378Snetchild bb->_max_locals = _max_locals; 924151378Snetchild bb->_max_stack = _max_stack; 925151378Snetchild bb->set_changed(false); 926151378Snetchild bb->_stack_top = BasicBlock::_dead_basic_block; // Initialize all basicblocks are dead. 927151378Snetchild bb->_monitor_top = bad_monitors; 928151378Snetchild 929151378Snetchild if (bbNo > 0) { 930151378Snetchild _basic_blocks[bbNo - 1]._end_bci = prev_bci; 931151378Snetchild } 932151378Snetchild 933151378Snetchild bbNo++; 934151378Snetchild } 935151378Snetchild // Remember prevous bci. 936151378Snetchild prev_bci = bci; 937151378Snetchild } 938151378Snetchild // Set 939151378Snetchild _basic_blocks[bbNo-1]._end_bci = prev_bci; 940151378Snetchild 941151378Snetchild 942151378Snetchild // Check that the correct number of basicblocks was found 943151378Snetchild if (bbNo !=_bb_count) { 944151378Snetchild if (bbNo < _bb_count) { 945151378Snetchild verify_error("jump into the middle of instruction?"); 946151378Snetchild return; 947151378Snetchild } else { 948151378Snetchild verify_error("extra basic blocks - should not happen?"); 949151378Snetchild return; 950151378Snetchild } 951151378Snetchild } 952151378Snetchild 953151378Snetchild _max_monitors = monitor_count; 954151378Snetchild 955151378Snetchild // Now that we have a bound on the depth of the monitor stack, we can 956151378Snetchild // initialize the CellTypeState-related information. 957151378Snetchild init_state(); 958151378Snetchild 959151378Snetchild // We allocate space for all state-vectors for all basicblocks in one huge chuck. 960151378Snetchild // Then in the next part of the code, we set a pointer in each _basic_block that 961151378Snetchild // points to each piece. 962151378Snetchild CellTypeState *basicBlockState = NEW_RESOURCE_ARRAY(CellTypeState, bbNo * _state_len); 963151378Snetchild memset(basicBlockState, 0, bbNo * _state_len * sizeof(CellTypeState)); 964151378Snetchild 965151378Snetchild // Make a pass over the basicblocks and assign their state vectors. 966151378Snetchild for (int blockNum=0; blockNum < bbNo; blockNum++) { 967151378Snetchild BasicBlock *bb = _basic_blocks + blockNum; 968151378Snetchild bb->_state = basicBlockState + blockNum * _state_len; 969151378Snetchild 970151378Snetchild#ifdef ASSERT 971151378Snetchild if (blockNum + 1 < bbNo) { 972151378Snetchild address bcp = _method->bcp_from(bb->_end_bci); 973151378Snetchild int bc_len = Bytecodes::java_length_at(bcp); 974151378Snetchild assert(bb->_end_bci + bc_len == bb[1]._bci, "unmatched bci info in basicblock"); 975151378Snetchild } 976151378Snetchild#endif 977151378Snetchild } 978151378Snetchild#ifdef ASSERT 979151378Snetchild { BasicBlock *bb = &_basic_blocks[bbNo-1]; 980151378Snetchild address bcp = _method->bcp_from(bb->_end_bci); 981151378Snetchild int bc_len = Bytecodes::java_length_at(bcp); 982151378Snetchild assert(bb->_end_bci + bc_len == _method->code_size(), "wrong end bci"); 983151378Snetchild } 984151378Snetchild#endif 985151378Snetchild 986151378Snetchild // Mark all alive blocks 987151378Snetchild mark_reachable_code(); 988151378Snetchild} 989151378Snetchild 990151378Snetchildvoid GenerateOopMap::setup_method_entry_state() { 991151378Snetchild 992151378Snetchild // Initialize all locals to 'uninit' and set stack-height to 0 993151378Snetchild make_context_uninitialized(); 994151378Snetchild 995151378Snetchild // Initialize CellState type of arguments 996151378Snetchild methodsig_to_effect(method()->signature(), method()->is_static(), vars()); 997151378Snetchild 998151378Snetchild // If some references must be pre-assigned to null, then set that up 999151378Snetchild initialize_vars(); 1000151378Snetchild 1001151378Snetchild // This is the start state 1002151378Snetchild merge_state_into_bb(&_basic_blocks[0]); 1003151378Snetchild 1004151378Snetchild assert(_basic_blocks[0].changed(), "we are not getting off the ground"); 1005151378Snetchild} 1006151378Snetchild 1007151378Snetchild// The instruction at bci is changing size by "delta". Update the basic blocks. 1008151378Snetchildvoid GenerateOopMap::update_basic_blocks(int bci, int delta, 1009151378Snetchild int new_method_size) { 1010151378Snetchild assert(new_method_size >= method()->code_size() + delta, 1011151378Snetchild "new method size is too small"); 1012151378Snetchild 1013151378Snetchild BitMap::bm_word_t* new_bb_hdr_bits = 1014151378Snetchild NEW_RESOURCE_ARRAY(BitMap::bm_word_t, 1015151378Snetchild BitMap::word_align_up(new_method_size)); 1016151378Snetchild _bb_hdr_bits.set_map(new_bb_hdr_bits); 1017151378Snetchild _bb_hdr_bits.set_size(new_method_size); 1018151378Snetchild _bb_hdr_bits.clear(); 1019151378Snetchild 1020151378Snetchild 1021151378Snetchild for(int k = 0; k < _bb_count; k++) { 1022151378Snetchild if (_basic_blocks[k]._bci > bci) { 1023151378Snetchild _basic_blocks[k]._bci += delta; 1024151378Snetchild _basic_blocks[k]._end_bci += delta; 1025151378Snetchild } 1026151378Snetchild _bb_hdr_bits.at_put(_basic_blocks[k]._bci, true); 1027151378Snetchild } 1028151378Snetchild} 1029151378Snetchild 1030151378Snetchild// 1031151378Snetchild// Initvars handling 1032151378Snetchild// 1033151378Snetchild 1034151378Snetchildvoid GenerateOopMap::initialize_vars() { 1035151378Snetchild for (int k = 0; k < _init_vars->length(); k++) 1036151378Snetchild _state[_init_vars->at(k)] = CellTypeState::make_slot_ref(k); 1037151378Snetchild} 1038151378Snetchild 1039151378Snetchildvoid GenerateOopMap::add_to_ref_init_set(int localNo) { 1040151378Snetchild 1041151378Snetchild if (TraceNewOopMapGeneration) 1042151378Snetchild tty->print_cr("Added init vars: %d", localNo); 1043151378Snetchild 1044151378Snetchild // Is it already in the set? 1045151378Snetchild if (_init_vars->contains(localNo) ) 1046151378Snetchild return; 1047151378Snetchild 1048151378Snetchild _init_vars->append(localNo); 1049151378Snetchild} 1050151378Snetchild 1051151378Snetchild// 1052151378Snetchild// Interpreration code 1053151378Snetchild// 1054151378Snetchild 1055151378Snetchildvoid GenerateOopMap::interp_all() { 1056151378Snetchild bool change = true; 1057151378Snetchild 1058151378Snetchild while (change && !_got_error) { 1059151378Snetchild change = false; 1060151378Snetchild for (int i = 0; i < _bb_count && !_got_error; i++) { 1061151378Snetchild BasicBlock *bb = &_basic_blocks[i]; 1062151378Snetchild if (bb->changed()) { 1063151378Snetchild if (_got_error) return; 1064151378Snetchild change = true; 1065151378Snetchild bb->set_changed(false); 1066151378Snetchild interp_bb(bb); 1067151378Snetchild } 1068151378Snetchild } 1069151378Snetchild } 1070151378Snetchild} 1071151378Snetchild 1072151378Snetchildvoid GenerateOopMap::interp_bb(BasicBlock *bb) { 1073151378Snetchild 1074151378Snetchild // We do not want to do anything in case the basic-block has not been initialized. This 1075151378Snetchild // will happen in the case where there is dead-code hang around in a method. 1076151378Snetchild assert(bb->is_reachable(), "should be reachable or deadcode exist"); 1077151378Snetchild restore_state(bb); 1078151378Snetchild 1079151378Snetchild BytecodeStream itr(_method); 1080151378Snetchild 1081151378Snetchild // Set iterator interval to be the current basicblock 1082151378Snetchild int lim_bci = next_bb_start_pc(bb); 1083151378Snetchild itr.set_interval(bb->_bci, lim_bci); 1084151378Snetchild assert(lim_bci != bb->_bci, "must be at least one instruction in a basicblock"); 1085151378Snetchild itr.next(); // read first instruction 1086151378Snetchild 1087151378Snetchild // Iterates through all bytecodes except the last in a basic block. 1088151378Snetchild // We handle the last one special, since there is controlflow change. 1089151378Snetchild while(itr.next_bci() < lim_bci && !_got_error) { 1090151378Snetchild if (_has_exceptions || _monitor_top != 0) { 1091151378Snetchild // We do not need to interpret the results of exceptional 1092151378Snetchild // continuation from this instruction when the method has no 1093151378Snetchild // exception handlers and the monitor stack is currently 1094151378Snetchild // empty. 1095151378Snetchild do_exception_edge(&itr); 1096151378Snetchild } 1097151378Snetchild interp1(&itr); 1098151378Snetchild itr.next(); 1099151378Snetchild } 1100151378Snetchild 1101151378Snetchild // Handle last instruction. 1102151378Snetchild if (!_got_error) { 1103151378Snetchild assert(itr.next_bci() == lim_bci, "must point to end"); 1104151378Snetchild if (_has_exceptions || _monitor_top != 0) { 1105151378Snetchild do_exception_edge(&itr); 1106151378Snetchild } 1107151378Snetchild interp1(&itr); 1108151378Snetchild 1109151378Snetchild bool fall_through = jump_targets_do(&itr, GenerateOopMap::merge_state, NULL); 1110151378Snetchild if (_got_error) return; 1111151378Snetchild 1112151378Snetchild if (itr.code() == Bytecodes::_ret) { 1113151378Snetchild assert(!fall_through, "cannot be set if ret instruction"); 1114151378Snetchild // Automatically handles 'wide' ret indicies 1115151378Snetchild ret_jump_targets_do(&itr, GenerateOopMap::merge_state, itr.get_index(), NULL); 1116151378Snetchild } else if (fall_through) { 1117151378Snetchild // Hit end of BB, but the instr. was a fall-through instruction, 1118151378Snetchild // so perform transition as if the BB ended in a "jump". 1119151378Snetchild if (lim_bci != bb[1]._bci) { 1120151378Snetchild verify_error("bytecodes fell through last instruction"); 1121151378Snetchild return; 1122151378Snetchild } 1123151378Snetchild merge_state_into_bb(bb + 1); 1124151378Snetchild } 1125151378Snetchild } 1126151378Snetchild} 1127151378Snetchild 1128151378Snetchildvoid GenerateOopMap::do_exception_edge(BytecodeStream* itr) { 1129151378Snetchild // Only check exception edge, if bytecode can trap 1130151378Snetchild if (!Bytecodes::can_trap(itr->code())) return; 1131151378Snetchild switch (itr->code()) { 1132151378Snetchild case Bytecodes::_aload_0: 1133151378Snetchild // These bytecodes can trap for rewriting. We need to assume that 1134151378Snetchild // they do not throw exceptions to make the monitor analysis work. 1135151378Snetchild return; 1136151378Snetchild 1137151378Snetchild case Bytecodes::_ireturn: 1138151378Snetchild case Bytecodes::_lreturn: 1139151378Snetchild case Bytecodes::_freturn: 1140151378Snetchild case Bytecodes::_dreturn: 1141151378Snetchild case Bytecodes::_areturn: 1142151378Snetchild case Bytecodes::_return: 1143151378Snetchild // If the monitor stack height is not zero when we leave the method, 1144151378Snetchild // then we are either exiting with a non-empty stack or we have 1145151378Snetchild // found monitor trouble earlier in our analysis. In either case, 1146151378Snetchild // assume an exception could be taken here. 1147151378Snetchild if (_monitor_top == 0) { 1148151378Snetchild return; 1149151378Snetchild } 1150151378Snetchild break; 1151151378Snetchild 1152151378Snetchild case Bytecodes::_monitorexit: 1153151378Snetchild // If the monitor stack height is bad_monitors, then we have detected a 1154151378Snetchild // monitor matching problem earlier in the analysis. If the 1155151378Snetchild // monitor stack height is 0, we are about to pop a monitor 1156151378Snetchild // off of an empty stack. In either case, the bytecode 1157151378Snetchild // could throw an exception. 1158151378Snetchild if (_monitor_top != bad_monitors && _monitor_top != 0) { 1159151378Snetchild return; 1160151378Snetchild } 1161151378Snetchild break; 1162151378Snetchild } 1163151378Snetchild 1164151378Snetchild if (_has_exceptions) { 1165151378Snetchild int bci = itr->bci(); 1166151378Snetchild typeArrayOop exct = method()->exception_table(); 1167151378Snetchild for(int i = 0; i< exct->length(); i+=4) { 1168151378Snetchild int start_pc = exct->int_at(i); 1169151378Snetchild int end_pc = exct->int_at(i+1); 1170151378Snetchild int handler_pc = exct->int_at(i+2); 1171151378Snetchild int catch_type = exct->int_at(i+3); 1172151378Snetchild 1173151378Snetchild if (start_pc <= bci && bci < end_pc) { 1174151378Snetchild BasicBlock *excBB = get_basic_block_at(handler_pc); 1175151378Snetchild CellTypeState *excStk = excBB->stack(); 1176151378Snetchild CellTypeState *cOpStck = stack(); 1177151378Snetchild CellTypeState cOpStck_0 = cOpStck[0]; 1178151378Snetchild int cOpStackTop = _stack_top; 1179151378Snetchild 1180151378Snetchild // Exception stacks are always the same. 1181151378Snetchild assert(method()->max_stack() > 0, "sanity check"); 1182151378Snetchild 1183151378Snetchild // We remembered the size and first element of "cOpStck" 1184151378Snetchild // above; now we temporarily set them to the appropriate 1185151378Snetchild // values for an exception handler. */ 1186151378Snetchild cOpStck[0] = CellTypeState::make_slot_ref(_max_locals); 1187151378Snetchild _stack_top = 1; 1188151378Snetchild 1189151378Snetchild merge_state_into_bb(excBB); 1190151378Snetchild 1191151378Snetchild // Now undo the temporary change. 1192151378Snetchild cOpStck[0] = cOpStck_0; 1193151378Snetchild _stack_top = cOpStackTop; 1194151378Snetchild 1195151378Snetchild // If this is a "catch all" handler, then we do not need to 1196151378Snetchild // consider any additional handlers. 1197151378Snetchild if (catch_type == 0) { 1198151378Snetchild return; 1199151378Snetchild } 1200151378Snetchild } 1201151378Snetchild } 1202151378Snetchild } 1203151378Snetchild 1204151378Snetchild // It is possible that none of the exception handlers would have caught 1205151378Snetchild // the exception. In this case, we will exit the method. We must 1206151378Snetchild // ensure that the monitor stack is empty in this case. 1207151378Snetchild if (_monitor_top == 0) { 1208151378Snetchild return; 1209151378Snetchild } 1210151378Snetchild 1211151378Snetchild // We pessimistically assume that this exception can escape the 1212151378Snetchild // method. (It is possible that it will always be caught, but 1213151378Snetchild // we don't care to analyse the types of the catch clauses.) 1214151378Snetchild 1215151378Snetchild // We don't set _monitor_top to bad_monitors because there are no successors 1216151378Snetchild // to this exceptional exit. 1217151378Snetchild 1218151378Snetchild if (TraceMonitorMismatch && _monitor_safe) { 1219151378Snetchild // We check _monitor_safe so that we only report the first mismatched 1220151378Snetchild // exceptional exit. 1221151378Snetchild report_monitor_mismatch("non-empty monitor stack at exceptional exit"); 1222151378Snetchild } 1223151378Snetchild _monitor_safe = false; 1224151378Snetchild 1225151378Snetchild} 1226151378Snetchild 1227151378Snetchildvoid GenerateOopMap::report_monitor_mismatch(const char *msg) { 1228151378Snetchild#ifndef PRODUCT 1229151378Snetchild tty->print(" Monitor mismatch in method "); 1230151378Snetchild method()->print_short_name(tty); 1231151378Snetchild tty->print_cr(": %s", msg); 1232151378Snetchild#endif 1233151378Snetchild} 1234151378Snetchild 1235151378Snetchildvoid GenerateOopMap::print_states(outputStream *os, 1236151378Snetchild CellTypeState* vec, int num) { 1237151378Snetchild for (int i = 0; i < num; i++) { 1238151378Snetchild vec[i].print(tty); 1239151378Snetchild } 1240151378Snetchild} 1241151378Snetchild 1242151378Snetchild// Print the state values at the current bytecode. 1243151378Snetchildvoid GenerateOopMap::print_current_state(outputStream *os, 1244151378Snetchild BytecodeStream *currentBC, 1245151378Snetchild bool detailed) { 1246151378Snetchild 1247151378Snetchild if (detailed) { 1248151378Snetchild os->print(" %4d vars = ", currentBC->bci()); 1249151378Snetchild print_states(os, vars(), _max_locals); 1250151378Snetchild os->print(" %s", Bytecodes::name(currentBC->code())); 1251151378Snetchild switch(currentBC->code()) { 1252151378Snetchild case Bytecodes::_invokevirtual: 1253151378Snetchild case Bytecodes::_invokespecial: 1254151378Snetchild case Bytecodes::_invokestatic: 1255151378Snetchild case Bytecodes::_invokeinterface: 1256151378Snetchild int idx = currentBC->get_index_big(); 1257151378Snetchild constantPoolOop cp = method()->constants(); 1258151378Snetchild int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); 1259151378Snetchild int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); 1260151378Snetchild symbolOop signature = cp->symbol_at(signatureIdx); 1261151378Snetchild os->print("%s", signature->as_C_string()); 1262151378Snetchild } 1263151378Snetchild os->cr(); 1264151378Snetchild os->print(" stack = "); 1265151378Snetchild print_states(os, stack(), _stack_top); 1266151378Snetchild os->cr(); 1267151378Snetchild if (_monitor_top != bad_monitors) { 1268151378Snetchild os->print(" monitors = "); 1269151378Snetchild print_states(os, monitors(), _monitor_top); 1270151378Snetchild } else { 1271151378Snetchild os->print(" [bad monitor stack]"); 1272151378Snetchild } 1273151378Snetchild os->cr(); 1274151378Snetchild } else { 1275151378Snetchild os->print(" %4d vars = '%s' ", currentBC->bci(), state_vec_to_string(vars(), _max_locals)); 1276151378Snetchild os->print(" stack = '%s' ", state_vec_to_string(stack(), _stack_top)); 1277151378Snetchild if (_monitor_top != bad_monitors) { 1278151378Snetchild os->print(" monitors = '%s' \t%s", state_vec_to_string(monitors(), _monitor_top), Bytecodes::name(currentBC->code())); 1279151378Snetchild } else { 1280151378Snetchild os->print(" [bad monitor stack]"); 1281151378Snetchild } 1282151378Snetchild switch(currentBC->code()) { 1283151378Snetchild case Bytecodes::_invokevirtual: 1284151378Snetchild case Bytecodes::_invokespecial: 1285151378Snetchild case Bytecodes::_invokestatic: 1286151378Snetchild case Bytecodes::_invokeinterface: 1287151378Snetchild int idx = currentBC->get_index_big(); 1288151378Snetchild constantPoolOop cp = method()->constants(); 1289151378Snetchild int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); 1290151378Snetchild int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); 1291151378Snetchild symbolOop signature = cp->symbol_at(signatureIdx); 1292151378Snetchild os->print("%s", signature->as_C_string()); 1293151378Snetchild } 1294151378Snetchild os->cr(); 1295151378Snetchild } 1296151378Snetchild} 1297151378Snetchild 1298151378Snetchild// Sets the current state to be the state after executing the 1299151378Snetchild// current instruction, starting in the current state. 1300151378Snetchildvoid GenerateOopMap::interp1(BytecodeStream *itr) { 1301151378Snetchild if (TraceNewOopMapGeneration) { 1302151378Snetchild print_current_state(tty, itr, TraceNewOopMapGenerationDetailed); 1303151378Snetchild } 1304151378Snetchild 1305151378Snetchild // Should we report the results? Result is reported *before* the instruction at the current bci is executed. 1306151378Snetchild // However, not for calls. For calls we do not want to include the arguments, so we postpone the reporting until 1307151378Snetchild // they have been popped (in method ppl). 1308151378Snetchild if (_report_result == true) { 1309151378Snetchild switch(itr->code()) { 1310151378Snetchild case Bytecodes::_invokevirtual: 1311151378Snetchild case Bytecodes::_invokespecial: 1312151378Snetchild case Bytecodes::_invokestatic: 1313151378Snetchild case Bytecodes::_invokeinterface: 1314151378Snetchild _itr_send = itr; 1315151378Snetchild _report_result_for_send = true; 1316151378Snetchild break; 1317151378Snetchild default: 1318151378Snetchild fill_stackmap_for_opcodes(itr, vars(), stack(), _stack_top); 1319151378Snetchild break; 1320151378Snetchild } 1321151378Snetchild } 1322151378Snetchild 1323151378Snetchild // abstract interpretation of current opcode 1324151378Snetchild switch(itr->code()) { 1325151378Snetchild case Bytecodes::_nop: break; 1326151378Snetchild case Bytecodes::_goto: break; 1327151378Snetchild case Bytecodes::_goto_w: break; 1328151378Snetchild case Bytecodes::_iinc: break; 1329151378Snetchild case Bytecodes::_return: do_return_monitor_check(); 1330151378Snetchild break; 1331151378Snetchild 1332151378Snetchild case Bytecodes::_aconst_null: 1333151378Snetchild case Bytecodes::_new: ppush1(CellTypeState::make_line_ref(itr->bci())); 1334151378Snetchild break; 1335151378Snetchild 1336151378Snetchild case Bytecodes::_iconst_m1: 1337151378Snetchild case Bytecodes::_iconst_0: 1338151378Snetchild case Bytecodes::_iconst_1: 1339151378Snetchild case Bytecodes::_iconst_2: 1340151378Snetchild case Bytecodes::_iconst_3: 1341151378Snetchild case Bytecodes::_iconst_4: 1342151378Snetchild case Bytecodes::_iconst_5: 1343151378Snetchild case Bytecodes::_fconst_0: 1344151378Snetchild case Bytecodes::_fconst_1: 1345151378Snetchild case Bytecodes::_fconst_2: 1346151378Snetchild case Bytecodes::_bipush: 1347151378Snetchild case Bytecodes::_sipush: ppush1(valCTS); break; 1348151378Snetchild 1349151378Snetchild case Bytecodes::_lconst_0: 1350151378Snetchild case Bytecodes::_lconst_1: 1351151378Snetchild case Bytecodes::_dconst_0: 1352151378Snetchild case Bytecodes::_dconst_1: ppush(vvCTS); break; 1353151378Snetchild 1354151378Snetchild case Bytecodes::_ldc2_w: ppush(vvCTS); break; 1355151378Snetchild 1356151378Snetchild case Bytecodes::_ldc: do_ldc(itr->get_index(), itr->bci()); break; 1357151378Snetchild case Bytecodes::_ldc_w: do_ldc(itr->get_index_big(), itr->bci());break; 1358151378Snetchild 1359151378Snetchild case Bytecodes::_iload: 1360151378Snetchild case Bytecodes::_fload: ppload(vCTS, itr->get_index()); break; 1361151378Snetchild 1362151378Snetchild case Bytecodes::_lload: 1363151378Snetchild case Bytecodes::_dload: ppload(vvCTS,itr->get_index()); break; 1364151378Snetchild 1365151378Snetchild case Bytecodes::_aload: ppload(rCTS, itr->get_index()); break; 1366151378Snetchild 1367151378Snetchild case Bytecodes::_iload_0: 1368151378Snetchild case Bytecodes::_fload_0: ppload(vCTS, 0); break; 1369151378Snetchild case Bytecodes::_iload_1: 1370151378Snetchild case Bytecodes::_fload_1: ppload(vCTS, 1); break; 1371151378Snetchild case Bytecodes::_iload_2: 1372151378Snetchild case Bytecodes::_fload_2: ppload(vCTS, 2); break; 1373151378Snetchild case Bytecodes::_iload_3: 1374151378Snetchild case Bytecodes::_fload_3: ppload(vCTS, 3); break; 1375151378Snetchild 1376151378Snetchild case Bytecodes::_lload_0: 1377151378Snetchild case Bytecodes::_dload_0: ppload(vvCTS, 0); break; 1378151378Snetchild case Bytecodes::_lload_1: 1379151378Snetchild case Bytecodes::_dload_1: ppload(vvCTS, 1); break; 1380151378Snetchild case Bytecodes::_lload_2: 1381151378Snetchild case Bytecodes::_dload_2: ppload(vvCTS, 2); break; 1382151378Snetchild case Bytecodes::_lload_3: 1383151378Snetchild case Bytecodes::_dload_3: ppload(vvCTS, 3); break; 1384151378Snetchild 1385151378Snetchild case Bytecodes::_aload_0: ppload(rCTS, 0); break; 1386151378Snetchild case Bytecodes::_aload_1: ppload(rCTS, 1); break; 1387151378Snetchild case Bytecodes::_aload_2: ppload(rCTS, 2); break; 1388151378Snetchild case Bytecodes::_aload_3: ppload(rCTS, 3); break; 1389151378Snetchild 1390151378Snetchild case Bytecodes::_iaload: 1391151378Snetchild case Bytecodes::_faload: 1392151378Snetchild case Bytecodes::_baload: 1393151378Snetchild case Bytecodes::_caload: 1394151378Snetchild case Bytecodes::_saload: pp(vrCTS, vCTS); break; 1395151378Snetchild 1396151378Snetchild case Bytecodes::_laload: pp(vrCTS, vvCTS); break; 1397151378Snetchild case Bytecodes::_daload: pp(vrCTS, vvCTS); break; 1398151378Snetchild 1399151378Snetchild case Bytecodes::_aaload: pp_new_ref(vrCTS, itr->bci()); break; 1400151378Snetchild 1401151378Snetchild case Bytecodes::_istore: 1402151378Snetchild case Bytecodes::_fstore: ppstore(vCTS, itr->get_index()); break; 1403151378Snetchild 1404151378Snetchild case Bytecodes::_lstore: 1405151378Snetchild case Bytecodes::_dstore: ppstore(vvCTS, itr->get_index()); break; 1406151378Snetchild 1407151378Snetchild case Bytecodes::_astore: do_astore(itr->get_index()); break; 1408151378Snetchild 1409151378Snetchild case Bytecodes::_istore_0: 1410151378Snetchild case Bytecodes::_fstore_0: ppstore(vCTS, 0); break; 1411151378Snetchild case Bytecodes::_istore_1: 1412151378Snetchild case Bytecodes::_fstore_1: ppstore(vCTS, 1); break; 1413151378Snetchild case Bytecodes::_istore_2: 1414151378Snetchild case Bytecodes::_fstore_2: ppstore(vCTS, 2); break; 1415151378Snetchild case Bytecodes::_istore_3: 1416151378Snetchild case Bytecodes::_fstore_3: ppstore(vCTS, 3); break; 1417151378Snetchild 1418151378Snetchild case Bytecodes::_lstore_0: 1419151378Snetchild case Bytecodes::_dstore_0: ppstore(vvCTS, 0); break; 1420151378Snetchild case Bytecodes::_lstore_1: 1421151378Snetchild case Bytecodes::_dstore_1: ppstore(vvCTS, 1); break; 1422151378Snetchild case Bytecodes::_lstore_2: 1423151378Snetchild case Bytecodes::_dstore_2: ppstore(vvCTS, 2); break; 1424151378Snetchild case Bytecodes::_lstore_3: 1425151378Snetchild case Bytecodes::_dstore_3: ppstore(vvCTS, 3); break; 1426151378Snetchild 1427151378Snetchild case Bytecodes::_astore_0: do_astore(0); break; 1428151378Snetchild case Bytecodes::_astore_1: do_astore(1); break; 1429151378Snetchild case Bytecodes::_astore_2: do_astore(2); break; 1430151378Snetchild case Bytecodes::_astore_3: do_astore(3); break; 1431151378Snetchild 1432151378Snetchild case Bytecodes::_iastore: 1433151378Snetchild case Bytecodes::_fastore: 1434151378Snetchild case Bytecodes::_bastore: 1435151378Snetchild case Bytecodes::_castore: 1436151378Snetchild case Bytecodes::_sastore: ppop(vvrCTS); break; 1437151378Snetchild case Bytecodes::_lastore: 1438151378Snetchild case Bytecodes::_dastore: ppop(vvvrCTS); break; 1439151378Snetchild case Bytecodes::_aastore: ppop(rvrCTS); break; 1440151378Snetchild 1441151378Snetchild case Bytecodes::_pop: ppop_any(1); break; 1442151378Snetchild case Bytecodes::_pop2: ppop_any(2); break; 1443151378Snetchild 1444151378Snetchild case Bytecodes::_dup: ppdupswap(1, "11"); break; 1445151378Snetchild case Bytecodes::_dup_x1: ppdupswap(2, "121"); break; 1446151378Snetchild case Bytecodes::_dup_x2: ppdupswap(3, "1321"); break; 1447151378Snetchild case Bytecodes::_dup2: ppdupswap(2, "2121"); break; 1448151378Snetchild case Bytecodes::_dup2_x1: ppdupswap(3, "21321"); break; 1449151378Snetchild case Bytecodes::_dup2_x2: ppdupswap(4, "214321"); break; 1450151378Snetchild case Bytecodes::_swap: ppdupswap(2, "12"); break; 1451151378Snetchild 1452151378Snetchild case Bytecodes::_iadd: 1453151378Snetchild case Bytecodes::_fadd: 1454151378Snetchild case Bytecodes::_isub: 1455151378Snetchild case Bytecodes::_fsub: 1456151378Snetchild case Bytecodes::_imul: 1457151378Snetchild case Bytecodes::_fmul: 1458151378Snetchild case Bytecodes::_idiv: 1459151378Snetchild case Bytecodes::_fdiv: 1460151378Snetchild case Bytecodes::_irem: 1461151378Snetchild case Bytecodes::_frem: 1462151378Snetchild case Bytecodes::_ishl: 1463151378Snetchild case Bytecodes::_ishr: 1464151378Snetchild case Bytecodes::_iushr: 1465151378Snetchild case Bytecodes::_iand: 1466151378Snetchild case Bytecodes::_ior: 1467151378Snetchild case Bytecodes::_ixor: 1468151378Snetchild case Bytecodes::_l2f: 1469151378Snetchild case Bytecodes::_l2i: 1470151378Snetchild case Bytecodes::_d2f: 1471151378Snetchild case Bytecodes::_d2i: 1472151378Snetchild case Bytecodes::_fcmpl: 1473151378Snetchild case Bytecodes::_fcmpg: pp(vvCTS, vCTS); break; 1474151378Snetchild 1475151378Snetchild case Bytecodes::_ladd: 1476151378Snetchild case Bytecodes::_dadd: 1477151378Snetchild case Bytecodes::_lsub: 1478151378Snetchild case Bytecodes::_dsub: 1479151378Snetchild case Bytecodes::_lmul: 1480151378Snetchild case Bytecodes::_dmul: 1481151378Snetchild case Bytecodes::_ldiv: 1482151378Snetchild case Bytecodes::_ddiv: 1483151378Snetchild case Bytecodes::_lrem: 1484151378Snetchild case Bytecodes::_drem: 1485151378Snetchild case Bytecodes::_land: 1486151378Snetchild case Bytecodes::_lor: 1487151378Snetchild case Bytecodes::_lxor: pp(vvvvCTS, vvCTS); break; 1488151378Snetchild 1489151378Snetchild case Bytecodes::_ineg: 1490151378Snetchild case Bytecodes::_fneg: 1491151378Snetchild case Bytecodes::_i2f: 1492151378Snetchild case Bytecodes::_f2i: 1493151378Snetchild case Bytecodes::_i2c: 1494151378Snetchild case Bytecodes::_i2s: 1495151378Snetchild case Bytecodes::_i2b: pp(vCTS, vCTS); break; 1496151378Snetchild 1497151378Snetchild case Bytecodes::_lneg: 1498151378Snetchild case Bytecodes::_dneg: 1499151378Snetchild case Bytecodes::_l2d: 1500151378Snetchild case Bytecodes::_d2l: pp(vvCTS, vvCTS); break; 1501151378Snetchild 1502151378Snetchild case Bytecodes::_lshl: 1503151378Snetchild case Bytecodes::_lshr: 1504151378Snetchild case Bytecodes::_lushr: pp(vvvCTS, vvCTS); break; 1505151378Snetchild 1506151378Snetchild case Bytecodes::_i2l: 1507151378Snetchild case Bytecodes::_i2d: 1508151378Snetchild case Bytecodes::_f2l: 1509151378Snetchild case Bytecodes::_f2d: pp(vCTS, vvCTS); break; 1510151378Snetchild 1511151378Snetchild case Bytecodes::_lcmp: pp(vvvvCTS, vCTS); break; 1512151378Snetchild case Bytecodes::_dcmpl: 1513151378Snetchild case Bytecodes::_dcmpg: pp(vvvvCTS, vCTS); break; 1514151378Snetchild 1515151378Snetchild case Bytecodes::_ifeq: 1516151378Snetchild case Bytecodes::_ifne: 1517151378Snetchild case Bytecodes::_iflt: 1518151378Snetchild case Bytecodes::_ifge: 1519151378Snetchild case Bytecodes::_ifgt: 1520151378Snetchild case Bytecodes::_ifle: 1521151378Snetchild case Bytecodes::_tableswitch: ppop1(valCTS); 1522151378Snetchild break; 1523151378Snetchild case Bytecodes::_ireturn: 1524151378Snetchild case Bytecodes::_freturn: do_return_monitor_check(); 1525151378Snetchild ppop1(valCTS); 1526151378Snetchild break; 1527151378Snetchild case Bytecodes::_if_icmpeq: 1528151378Snetchild case Bytecodes::_if_icmpne: 1529151378Snetchild case Bytecodes::_if_icmplt: 1530151378Snetchild case Bytecodes::_if_icmpge: 1531151378Snetchild case Bytecodes::_if_icmpgt: 1532151378Snetchild case Bytecodes::_if_icmple: ppop(vvCTS); 1533151378Snetchild break; 1534151378Snetchild 1535151378Snetchild case Bytecodes::_lreturn: do_return_monitor_check(); 1536151378Snetchild ppop(vvCTS); 1537151378Snetchild break; 1538151378Snetchild 1539151378Snetchild case Bytecodes::_dreturn: do_return_monitor_check(); 1540151378Snetchild ppop(vvCTS); 1541151378Snetchild break; 1542151378Snetchild 1543151378Snetchild case Bytecodes::_if_acmpeq: 1544151378Snetchild case Bytecodes::_if_acmpne: ppop(rrCTS); break; 1545151378Snetchild 1546151378Snetchild case Bytecodes::_jsr: do_jsr(itr->dest()); break; 1547151378Snetchild case Bytecodes::_jsr_w: do_jsr(itr->dest_w()); break; 1548151378Snetchild 1549151378Snetchild case Bytecodes::_getstatic: do_field(true, true, 1550151378Snetchild itr->get_index_big(), 1551151378Snetchild itr->bci()); break; 1552151378Snetchild case Bytecodes::_putstatic: do_field(false, true, itr->get_index_big(), itr->bci()); break; 1553151378Snetchild case Bytecodes::_getfield: do_field(true, false, itr->get_index_big(), itr->bci()); break; 1554151378Snetchild case Bytecodes::_putfield: do_field(false, false, itr->get_index_big(), itr->bci()); break; 1555151378Snetchild 1556151378Snetchild case Bytecodes::_invokevirtual: 1557151378Snetchild case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; 1558151378Snetchild case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break; 1559151378Snetchild case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break; 1560151378Snetchild case Bytecodes::_newarray: 1561151378Snetchild case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; 1562151378Snetchild case Bytecodes::_checkcast: do_checkcast(); break; 1563151378Snetchild case Bytecodes::_arraylength: 1564151378Snetchild case Bytecodes::_instanceof: pp(rCTS, vCTS); break; 1565151378Snetchild case Bytecodes::_monitorenter: do_monitorenter(itr->bci()); break; 1566151378Snetchild case Bytecodes::_monitorexit: do_monitorexit(itr->bci()); break; 1567151378Snetchild 1568151378Snetchild case Bytecodes::_athrow: // handled by do_exception_edge() BUT ... 1569151378Snetchild // vlh(apple): do_exception_edge() does not get 1570151378Snetchild // called if method has no exception handlers 1571151378Snetchild if ((!_has_exceptions) && (_monitor_top > 0)) { 1572151378Snetchild _monitor_safe = false; 1573151378Snetchild } 1574151378Snetchild break; 1575151378Snetchild 1576151378Snetchild case Bytecodes::_areturn: do_return_monitor_check(); 1577151378Snetchild ppop1(refCTS); 1578151378Snetchild break; 1579151378Snetchild case Bytecodes::_ifnull: 1580151378Snetchild case Bytecodes::_ifnonnull: ppop1(refCTS); break; 1581151378Snetchild case Bytecodes::_multianewarray: do_multianewarray(*(itr->bcp()+3), itr->bci()); break; 1582151378Snetchild 1583151378Snetchild case Bytecodes::_wide: fatal("Iterator should skip this bytecode"); break; 1584151378Snetchild case Bytecodes::_ret: break; 1585151378Snetchild 1586151378Snetchild // Java opcodes 1587151378Snetchild case Bytecodes::_lookupswitch: ppop1(valCTS); break; 1588151378Snetchild 1589151378Snetchild default: 1590151378Snetchild tty->print("unexpected opcode: %d\n", itr->code()); 1591151378Snetchild ShouldNotReachHere(); 1592151378Snetchild break; 1593151378Snetchild } 1594151378Snetchild} 1595151378Snetchild 1596151378Snetchildvoid GenerateOopMap::check_type(CellTypeState expected, CellTypeState actual) { 1597151378Snetchild if (!expected.equal_kind(actual)) { 1598151378Snetchild verify_error("wrong type on stack (found: %c expected: %c)", actual.to_char(), expected.to_char()); 1599151378Snetchild } 1600151378Snetchild} 1601151378Snetchild 1602151378Snetchildvoid GenerateOopMap::ppstore(CellTypeState *in, int loc_no) { 1603151378Snetchild while(!(*in).is_bottom()) { 1604151378Snetchild CellTypeState expected =*in++; 1605151378Snetchild CellTypeState actual = pop(); 1606151378Snetchild check_type(expected, actual); 1607151378Snetchild assert(loc_no >= 0, "sanity check"); 1608151378Snetchild set_var(loc_no++, actual); 1609151378Snetchild } 1610151378Snetchild} 1611151378Snetchild 1612151378Snetchildvoid GenerateOopMap::ppload(CellTypeState *out, int loc_no) { 1613151378Snetchild while(!(*out).is_bottom()) { 1614151378Snetchild CellTypeState out1 = *out++; 1615151378Snetchild CellTypeState vcts = get_var(loc_no); 1616151378Snetchild assert(out1.can_be_reference() || out1.can_be_value(), 1617151378Snetchild "can only load refs. and values."); 1618151378Snetchild if (out1.is_reference()) { 1619151378Snetchild assert(loc_no>=0, "sanity check"); 1620151378Snetchild if (!vcts.is_reference()) { 1621151378Snetchild // We were asked to push a reference, but the type of the 1622151378Snetchild // variable can be something else 1623151378Snetchild _conflict = true; 1624151378Snetchild if (vcts.can_be_uninit()) { 1625151378Snetchild // It is a ref-uninit conflict (at least). If there are other 1626151378Snetchild // problems, we'll get them in the next round 1627151378Snetchild add_to_ref_init_set(loc_no); 1628151378Snetchild vcts = out1; 1629151378Snetchild } else { 1630151378Snetchild // It wasn't a ref-uninit conflict. So must be a 1631151378Snetchild // ref-val or ref-pc conflict. Split the variable. 1632151378Snetchild record_refval_conflict(loc_no); 1633151378Snetchild vcts = out1; 1634151378Snetchild } 1635151378Snetchild push(out1); // recover... 1636151378Snetchild } else { 1637151378Snetchild push(vcts); // preserve reference. 1638151378Snetchild } 1639151378Snetchild // Otherwise it is a conflict, but one that verification would 1640151378Snetchild // have caught if illegal. In particular, it can't be a topCTS 1641151378Snetchild // resulting from mergeing two difference pcCTS's since the verifier 1642151378Snetchild // would have rejected any use of such a merge. 1643151378Snetchild } else { 1644151378Snetchild push(out1); // handle val/init conflict 1645151378Snetchild } 1646151378Snetchild loc_no++; 1647151378Snetchild } 1648151378Snetchild} 1649151378Snetchild 1650151378Snetchildvoid GenerateOopMap::ppdupswap(int poplen, const char *out) { 1651151378Snetchild CellTypeState actual[5]; 1652151378Snetchild assert(poplen < 5, "this must be less than length of actual vector"); 1653151378Snetchild 1654151378Snetchild // pop all arguments 1655151378Snetchild for(int i = 0; i < poplen; i++) actual[i] = pop(); 1656151378Snetchild 1657151378Snetchild // put them back 1658151378Snetchild char push_ch = *out++; 1659151378Snetchild while (push_ch != '\0') { 1660151378Snetchild int idx = push_ch - '1'; 1661151378Snetchild assert(idx >= 0 && idx < poplen, "wrong arguments"); 1662151378Snetchild push(actual[idx]); 1663151378Snetchild push_ch = *out++; 1664151378Snetchild } 1665151378Snetchild} 1666151378Snetchild 1667151378Snetchildvoid GenerateOopMap::ppop1(CellTypeState out) { 1668151378Snetchild CellTypeState actual = pop(); 1669151378Snetchild check_type(out, actual); 1670151378Snetchild} 1671151378Snetchild 1672151378Snetchildvoid GenerateOopMap::ppop(CellTypeState *out) { 1673151378Snetchild while (!(*out).is_bottom()) { 1674151378Snetchild ppop1(*out++); 1675151378Snetchild } 1676151378Snetchild} 1677151378Snetchild 1678151378Snetchildvoid GenerateOopMap::ppush1(CellTypeState in) { 1679151378Snetchild assert(in.is_reference() | in.is_value(), "sanity check"); 1680151378Snetchild push(in); 1681151378Snetchild} 1682151378Snetchild 1683151378Snetchildvoid GenerateOopMap::ppush(CellTypeState *in) { 1684151378Snetchild while (!(*in).is_bottom()) { 1685151378Snetchild ppush1(*in++); 1686151378Snetchild } 1687151378Snetchild} 1688151378Snetchild 1689151378Snetchildvoid GenerateOopMap::pp(CellTypeState *in, CellTypeState *out) { 1690151378Snetchild ppop(in); 1691151378Snetchild ppush(out); 1692151378Snetchild} 1693151378Snetchild 1694151378Snetchildvoid GenerateOopMap::pp_new_ref(CellTypeState *in, int bci) { 1695151378Snetchild ppop(in); 1696151378Snetchild ppush1(CellTypeState::make_line_ref(bci)); 1697151378Snetchild} 1698151378Snetchild 1699151378Snetchildvoid GenerateOopMap::ppop_any(int poplen) { 1700151378Snetchild if (_stack_top >= poplen) { 1701151378Snetchild _stack_top -= poplen; 1702151378Snetchild } else { 1703151378Snetchild verify_error("stack underflow"); 1704151378Snetchild } 1705151378Snetchild} 1706151378Snetchild 1707151378Snetchild// Replace all occurences of the state 'match' with the state 'replace' 1708151378Snetchild// in our current state vector. 1709151378Snetchildvoid GenerateOopMap::replace_all_CTS_matches(CellTypeState match, 1710151378Snetchild CellTypeState replace) { 1711151378Snetchild int i; 1712151378Snetchild int len = _max_locals + _stack_top; 1713151378Snetchild bool change = false; 1714151378Snetchild 1715151378Snetchild for (i = len - 1; i >= 0; i--) { 1716151378Snetchild if (match.equal(_state[i])) { 1717151378Snetchild _state[i] = replace; 1718151378Snetchild } 1719151378Snetchild } 1720151378Snetchild 1721151378Snetchild if (_monitor_top > 0) { 1722151378Snetchild int base = _max_locals + _max_stack; 1723151378Snetchild len = base + _monitor_top; 1724151378Snetchild for (i = len - 1; i >= base; i--) { 1725151378Snetchild if (match.equal(_state[i])) { 1726151378Snetchild _state[i] = replace; 1727151378Snetchild } 1728151378Snetchild } 1729151378Snetchild } 1730151378Snetchild} 1731151378Snetchild 1732151378Snetchildvoid GenerateOopMap::do_checkcast() { 1733151378Snetchild CellTypeState actual = pop(); 1734151378Snetchild check_type(refCTS, actual); 1735151378Snetchild push(actual); 1736151378Snetchild} 1737151378Snetchild 1738151378Snetchildvoid GenerateOopMap::do_monitorenter(int bci) { 1739151378Snetchild CellTypeState actual = pop(); 1740151378Snetchild if (_monitor_top == bad_monitors) { 1741151378Snetchild return; 1742151378Snetchild } 1743151378Snetchild 1744151378Snetchild // Bail out when we get repeated locks on an identical monitor. This case 1745151378Snetchild // isn't too hard to handle and can be made to work if supporting nested 1746151378Snetchild // redundant synchronized statements becomes a priority. 1747151378Snetchild // 1748151378Snetchild // See also "Note" in do_monitorexit(), below. 1749151378Snetchild if (actual.is_lock_reference()) { 1750151378Snetchild _monitor_top = bad_monitors; 1751151378Snetchild _monitor_safe = false; 1752151378Snetchild 1753151378Snetchild if (TraceMonitorMismatch) { 1754151378Snetchild report_monitor_mismatch("nested redundant lock -- bailout..."); 1755151378Snetchild } 1756151378Snetchild return; 1757151378Snetchild } 1758151378Snetchild 1759151378Snetchild CellTypeState lock = CellTypeState::make_lock_ref(bci); 1760151378Snetchild check_type(refCTS, actual); 1761151378Snetchild if (!actual.is_info_top()) { 1762151378Snetchild replace_all_CTS_matches(actual, lock); 1763151378Snetchild monitor_push(lock); 1764151378Snetchild } 1765151378Snetchild} 1766151378Snetchild 1767151378Snetchildvoid GenerateOopMap::do_monitorexit(int bci) { 1768151378Snetchild CellTypeState actual = pop(); 1769151378Snetchild if (_monitor_top == bad_monitors) { 1770151378Snetchild return; 1771151378Snetchild } 1772151378Snetchild check_type(refCTS, actual); 1773151378Snetchild CellTypeState expected = monitor_pop(); 1774151378Snetchild if (!actual.is_lock_reference() || !expected.equal(actual)) { 1775151378Snetchild // The monitor we are exiting is not verifiably the one 1776151378Snetchild // on the top of our monitor stack. This causes a monitor 1777151378Snetchild // mismatch. 1778151378Snetchild _monitor_top = bad_monitors; 1779151378Snetchild _monitor_safe = false; 1780151378Snetchild 1781151378Snetchild // We need to mark this basic block as changed so that 1782151378Snetchild // this monitorexit will be visited again. We need to 1783151378Snetchild // do this to ensure that we have accounted for the 1784151378Snetchild // possibility that this bytecode will throw an 1785151378Snetchild // exception. 1786151378Snetchild BasicBlock* bb = get_basic_block_containing(bci); 1787151378Snetchild bb->set_changed(true); 1788151378Snetchild bb->_monitor_top = bad_monitors; 1789151378Snetchild 1790151378Snetchild if (TraceMonitorMismatch) { 1791151378Snetchild report_monitor_mismatch("improper monitor pair"); 1792151378Snetchild } 1793151378Snetchild } else { 1794151378Snetchild // This code is a fix for the case where we have repeated 1795151378Snetchild // locking of the same object in straightline code. We clear 1796151378Snetchild // out the lock when it is popped from the monitor stack 1797151378Snetchild // and replace it with an unobtrusive reference value that can 1798151378Snetchild // be locked again. 1799151378Snetchild // 1800151378Snetchild // Note: when generateOopMap is fixed to properly handle repeated, 1801151378Snetchild // nested, redundant locks on the same object, then this 1802151378Snetchild // fix will need to be removed at that time. 1803151378Snetchild replace_all_CTS_matches(actual, CellTypeState::make_line_ref(bci)); 1804151378Snetchild } 1805151378Snetchild} 1806151378Snetchild 1807151378Snetchildvoid GenerateOopMap::do_return_monitor_check() { 1808151378Snetchild if (_monitor_top > 0) { 1809151378Snetchild // The monitor stack must be empty when we leave the method 1810151378Snetchild // for the monitors to be properly matched. 1811151378Snetchild _monitor_safe = false; 1812151378Snetchild 1813151378Snetchild // Since there are no successors to the *return bytecode, it 1814151378Snetchild // isn't necessary to set _monitor_top to bad_monitors. 1815151378Snetchild 1816151378Snetchild if (TraceMonitorMismatch) { 1817151378Snetchild report_monitor_mismatch("non-empty monitor stack at return"); 1818151378Snetchild } 1819151378Snetchild } 1820151378Snetchild} 1821151378Snetchild 1822151378Snetchildvoid GenerateOopMap::do_jsr(int targ_bci) { 1823151378Snetchild push(CellTypeState::make_addr(targ_bci)); 1824151378Snetchild} 1825151378Snetchild 1826151378Snetchild 1827151378Snetchild 1828151378Snetchildvoid GenerateOopMap::do_ldc(int idx, int bci) { 1829151378Snetchild constantPoolOop cp = method()->constants(); 1830151378Snetchild constantTag tag = cp->tag_at(idx); 1831151378Snetchild 1832151378Snetchild CellTypeState cts = (tag.is_string() || tag.is_unresolved_string() || 1833151378Snetchild tag.is_klass() || tag.is_unresolved_klass()) 1834151378Snetchild ? CellTypeState::make_line_ref(bci) : valCTS; 1835151378Snetchild ppush1(cts); 1836151378Snetchild} 1837151378Snetchild 1838151378Snetchildvoid GenerateOopMap::do_multianewarray(int dims, int bci) { 1839151378Snetchild assert(dims >= 1, "sanity check"); 1840151378Snetchild for(int i = dims -1; i >=0; i--) { 1841151378Snetchild ppop1(valCTS); 1842151378Snetchild } 1843151378Snetchild ppush1(CellTypeState::make_line_ref(bci)); 1844151378Snetchild} 1845151378Snetchild 1846151378Snetchildvoid GenerateOopMap::do_astore(int idx) { 1847151378Snetchild CellTypeState r_or_p = pop(); 1848151378Snetchild if (!r_or_p.is_address() && !r_or_p.is_reference()) { 1849151378Snetchild // We actually expected ref or pc, but we only report that we expected a ref. It does not 1850151378Snetchild // really matter (at least for now) 1851151378Snetchild verify_error("wrong type on stack (found: %c, expected: {pr})", r_or_p.to_char()); 1852151378Snetchild return; 1853151378Snetchild } 1854151378Snetchild set_var(idx, r_or_p); 1855151378Snetchild} 1856151378Snetchild 1857151378Snetchild// Copies bottom/zero terminated CTS string from "src" into "dst". 1858151378Snetchild// Does NOT terminate with a bottom. Returns the number of cells copied. 1859151378Snetchildint GenerateOopMap::copy_cts(CellTypeState *dst, CellTypeState *src) { 1860151378Snetchild int idx = 0; 1861151378Snetchild while (!src[idx].is_bottom()) { 1862151378Snetchild dst[idx] = src[idx]; 1863151378Snetchild idx++; 1864151378Snetchild } 1865151378Snetchild return idx; 1866151378Snetchild} 1867151378Snetchild 1868151378Snetchildvoid GenerateOopMap::do_field(int is_get, int is_static, int idx, int bci) { 1869151378Snetchild // Dig up signature for field in constant pool 1870151378Snetchild constantPoolOop cp = method()->constants(); 1871151378Snetchild int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); 1872151378Snetchild int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); 1873151378Snetchild symbolOop signature = cp->symbol_at(signatureIdx); 1874151378Snetchild 1875151378Snetchild // Parse signature (espcially simple for fields) 1876151378Snetchild assert(signature->utf8_length() > 0, "field signatures cannot have zero length"); 1877151378Snetchild // The signature is UFT8 encoded, but the first char is always ASCII for signatures. 1878151378Snetchild char sigch = (char)*(signature->base()); 1879151378Snetchild CellTypeState temp[4]; 1880151378Snetchild CellTypeState *eff = sigchar_to_effect(sigch, bci, temp); 1881151378Snetchild 1882151378Snetchild CellTypeState in[4]; 1883151378Snetchild CellTypeState *out; 1884151378Snetchild int i = 0; 1885151378Snetchild 1886151378Snetchild if (is_get) { 1887151378Snetchild out = eff; 1888151378Snetchild } else { 1889151378Snetchild out = epsilonCTS; 1890151378Snetchild i = copy_cts(in, eff); 1891151378Snetchild } 1892151378Snetchild if (!is_static) in[i++] = CellTypeState::ref; 1893151378Snetchild in[i] = CellTypeState::bottom; 1894151378Snetchild assert(i<=3, "sanity check"); 1895151378Snetchild pp(in, out); 1896151378Snetchild} 1897151378Snetchild 1898151378Snetchildvoid GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) { 1899151378Snetchild // Dig up signature for field in constant pool 1900151378Snetchild constantPoolOop cp = _method->constants(); 1901151378Snetchild int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); 1902151378Snetchild int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); 1903151378Snetchild symbolOop signature = cp->symbol_at(signatureIdx); 1904151378Snetchild 1905151378Snetchild // Parse method signature 1906151378Snetchild CellTypeState out[4]; 1907151378Snetchild CellTypeState in[MAXARGSIZE+1]; // Includes result 1908151378Snetchild ComputeCallStack cse(signature); 1909151378Snetchild 1910151378Snetchild // Compute return type 1911151378Snetchild int res_length= cse.compute_for_returntype(out); 1912151378Snetchild 1913151378Snetchild // Temporary hack. 1914151378Snetchild if (out[0].equal(CellTypeState::ref) && out[1].equal(CellTypeState::bottom)) { 1915151378Snetchild out[0] = CellTypeState::make_line_ref(bci); 1916151378Snetchild } 1917151378Snetchild 1918151378Snetchild assert(res_length<=4, "max value should be vv"); 1919151378Snetchild 1920151378Snetchild // Compute arguments 1921151378Snetchild int arg_length = cse.compute_for_parameters(is_static != 0, in); 1922151378Snetchild assert(arg_length<=MAXARGSIZE, "too many locals"); 1923151378Snetchild 1924151378Snetchild // Pop arguments 1925151378Snetchild for (int i = arg_length - 1; i >= 0; i--) ppop1(in[i]);// Do args in reverse order. 1926151378Snetchild 1927151378Snetchild // Report results 1928151378Snetchild if (_report_result_for_send == true) { 1929151378Snetchild fill_stackmap_for_opcodes(_itr_send, vars(), stack(), _stack_top); 1930151378Snetchild _report_result_for_send = false; 1931151378Snetchild } 1932151378Snetchild 1933151378Snetchild // Push return address 1934151378Snetchild ppush(out); 1935151378Snetchild} 1936151378Snetchild 1937151378Snetchild// This is used to parse the signature for fields, since they are very simple... 1938151378SnetchildCellTypeState *GenerateOopMap::sigchar_to_effect(char sigch, int bci, CellTypeState *out) { 1939151378Snetchild // Object and array 1940151378Snetchild if (sigch=='L' || sigch=='[') { 1941151378Snetchild out[0] = CellTypeState::make_line_ref(bci); 1942151378Snetchild out[1] = CellTypeState::bottom; 1943151378Snetchild return out; 1944151378Snetchild } 1945151378Snetchild if (sigch == 'J' || sigch == 'D' ) return vvCTS; // Long and Double 1946151378Snetchild if (sigch == 'V' ) return epsilonCTS; // Void 1947151378Snetchild return vCTS; // Otherwise 1948151378Snetchild} 1949151378Snetchild 1950151378Snetchildlong GenerateOopMap::_total_byte_count = 0; 1951151378SnetchildelapsedTimer GenerateOopMap::_total_oopmap_time; 1952151378Snetchild 1953151378Snetchild// This function assumes "bcs" is at a "ret" instruction and that the vars 1954151378Snetchild// state is valid for that instruction. Furthermore, the ret instruction 1955151378Snetchild// must be the last instruction in "bb" (we store information about the 1956151378Snetchild// "ret" in "bb"). 1957151378Snetchildvoid GenerateOopMap::ret_jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int varNo, int *data) { 1958151378Snetchild CellTypeState ra = vars()[varNo]; 1959151378Snetchild if (!ra.is_good_address()) { 1960151378Snetchild verify_error("ret returns from two jsr subroutines?"); 1961151378Snetchild return; 1962151378Snetchild } 1963151378Snetchild int target = ra.get_info(); 1964151378Snetchild 1965151378Snetchild RetTableEntry* rtEnt = _rt.find_jsrs_for_target(target); 1966151378Snetchild int bci = bcs->bci(); 1967151378Snetchild for (int i = 0; i < rtEnt->nof_jsrs(); i++) { 1968151378Snetchild int target_bci = rtEnt->jsrs(i); 1969151378Snetchild // Make sure a jrtRet does not set the changed bit for dead basicblock. 1970151378Snetchild BasicBlock* jsr_bb = get_basic_block_containing(target_bci - 1); 1971151378Snetchild debug_only(BasicBlock* target_bb = &jsr_bb[1];) 1972151378Snetchild assert(target_bb == get_basic_block_at(target_bci), "wrong calc. of successor basicblock"); 1973151378Snetchild bool alive = jsr_bb->is_alive(); 1974151378Snetchild if (TraceNewOopMapGeneration) { 1975151378Snetchild tty->print("pc = %d, ret -> %d alive: %s\n", bci, target_bci, alive ? "true" : "false"); 1976151378Snetchild } 1977151378Snetchild if (alive) jmpFct(this, target_bci, data); 1978151378Snetchild } 1979151378Snetchild} 1980151378Snetchild 1981151378Snetchild// 1982151378Snetchild// Debug method 1983151378Snetchild// 1984151378Snetchildchar* GenerateOopMap::state_vec_to_string(CellTypeState* vec, int len) { 1985151378Snetchild#ifdef ASSERT 1986151378Snetchild int checklen = MAX3(_max_locals, _max_stack, _max_monitors) + 1; 1987151378Snetchild assert(len < checklen, "state_vec_buf overflow"); 1988151378Snetchild#endif 1989151378Snetchild for (int i = 0; i < len; i++) _state_vec_buf[i] = vec[i].to_char(); 1990151378Snetchild _state_vec_buf[len] = 0; 1991151378Snetchild return _state_vec_buf; 1992151378Snetchild} 1993151378Snetchild 1994151378Snetchildvoid GenerateOopMap::print_time() { 1995151378Snetchild tty->print_cr ("Accumulated oopmap times:"); 1996151378Snetchild tty->print_cr ("---------------------------"); 1997151378Snetchild tty->print_cr (" Total : %3.3f sec.", GenerateOopMap::_total_oopmap_time.seconds()); 1998151378Snetchild tty->print_cr (" (%3.0f bytecodes per sec) ", 1999151378Snetchild GenerateOopMap::_total_byte_count / GenerateOopMap::_total_oopmap_time.seconds()); 2000151378Snetchild} 2001151378Snetchild 2002151378Snetchild// 2003151378Snetchild// ============ Main Entry Point =========== 2004151378Snetchild// 2005151378SnetchildGenerateOopMap::GenerateOopMap(methodHandle method) { 2006151378Snetchild // We have to initialize all variables here, that can be queried direcly 2007151378Snetchild _method = method; 2008151378Snetchild _max_locals=0; 2009151378Snetchild _init_vars = NULL; 2010151378Snetchild 2011151378Snetchild#ifndef PRODUCT 2012151378Snetchild // If we are doing a detailed trace, include the regular trace information. 2013151378Snetchild if (TraceNewOopMapGenerationDetailed) { 2014151378Snetchild TraceNewOopMapGeneration = true; 2015151378Snetchild } 2016151378Snetchild#endif 2017151378Snetchild} 2018151378Snetchild 2019151378Snetchildvoid GenerateOopMap::compute_map(TRAPS) { 2020151378Snetchild#ifndef PRODUCT 2021151378Snetchild if (TimeOopMap2) { 2022151378Snetchild method()->print_short_name(tty); 2023151378Snetchild tty->print(" "); 2024151378Snetchild } 2025151378Snetchild if (TimeOopMap) { 2026151378Snetchild _total_byte_count += method()->code_size(); 2027151378Snetchild } 2028151378Snetchild#endif 2029151378Snetchild TraceTime t_single("oopmap time", TimeOopMap2); 2030151378Snetchild TraceTime t_all(NULL, &_total_oopmap_time, TimeOopMap); 2031151378Snetchild 2032151378Snetchild // Initialize values 2033151378Snetchild _got_error = false; 2034151378Snetchild _conflict = false; 2035151378Snetchild _max_locals = method()->max_locals(); 2036151378Snetchild _max_stack = method()->max_stack(); 2037151378Snetchild _has_exceptions = (method()->exception_table()->length() > 0); 2038151378Snetchild _nof_refval_conflicts = 0; 2039151378Snetchild _init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars 2040151378Snetchild _report_result = false; 2041151378Snetchild _report_result_for_send = false; 2042151378Snetchild _new_var_map = NULL; 2043151378Snetchild _ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number; 2044151378Snetchild _did_rewriting = false; 2045151378Snetchild _did_relocation = false; 2046151378Snetchild 2047151378Snetchild if (TraceNewOopMapGeneration) { 2048151378Snetchild tty->print("Method name: %s\n", method()->name()->as_C_string()); 2049151378Snetchild if (Verbose) { 2050151378Snetchild _method->print_codes(); 2051151378Snetchild tty->print_cr("Exception table:"); 2052151378Snetchild typeArrayOop excps = method()->exception_table(); 2053151378Snetchild for(int i = 0; i < excps->length(); i += 4) { 2054151378Snetchild tty->print_cr("[%d - %d] -> %d", excps->int_at(i + 0), excps->int_at(i + 1), excps->int_at(i + 2)); 2055151378Snetchild } 2056151378Snetchild } 2057151378Snetchild } 2058151378Snetchild 2059151378Snetchild // if no code - do nothing 2060151378Snetchild // compiler needs info 2061151378Snetchild if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) { 2062151378Snetchild fill_stackmap_prolog(0); 2063151378Snetchild fill_stackmap_epilog(); 2064151378Snetchild return; 2065151378Snetchild } 2066151378Snetchild // Step 1: Compute all jump targets and their return value 2067151378Snetchild if (!_got_error) 2068151378Snetchild _rt.compute_ret_table(_method); 2069151378Snetchild 2070151378Snetchild // Step 2: Find all basic blocks and count GC points 2071151378Snetchild if (!_got_error) 2072151378Snetchild mark_bbheaders_and_count_gc_points(); 2073151378Snetchild 2074151378Snetchild // Step 3: Calculate stack maps 2075151378Snetchild if (!_got_error) 2076151378Snetchild do_interpretation(); 2077151378Snetchild 2078151378Snetchild // Step 4:Return results 2079151378Snetchild if (!_got_error && report_results()) 2080151378Snetchild report_result(); 2081151378Snetchild 2082151378Snetchild if (_got_error) { 2083151378Snetchild THROW_HANDLE(_exception); 2084151378Snetchild } 2085151378Snetchild} 2086151378Snetchild 2087151378Snetchild// Error handling methods 2088151378Snetchild// These methods create an exception for the current thread which is thrown 2089151378Snetchild// at the bottom of the call stack, when it returns to compute_map(). The 2090151378Snetchild// _got_error flag controls execution. NOT TODO: The VM exception propagation 2091151378Snetchild// mechanism using TRAPS/CHECKs could be used here instead but it would need 2092151378Snetchild// to be added as a parameter to every function and checked for every call. 2093151378Snetchild// The tons of extra code it would generate didn't seem worth the change. 2094151378Snetchild// 2095151378Snetchildvoid GenerateOopMap::error_work(const char *format, va_list ap) { 2096151378Snetchild _got_error = true; 2097151378Snetchild char msg_buffer[512]; 2098151378Snetchild vsnprintf(msg_buffer, sizeof(msg_buffer), format, ap); 2099151378Snetchild // Append method name 2100151378Snetchild char msg_buffer2[512]; 2101151378Snetchild jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string()); 2102151378Snetchild _exception = Exceptions::new_exception(Thread::current(), 2103151378Snetchild vmSymbols::java_lang_LinkageError(), msg_buffer2); 2104151378Snetchild} 2105151378Snetchild 2106151378Snetchildvoid GenerateOopMap::report_error(const char *format, ...) { 2107151378Snetchild va_list ap; 2108151378Snetchild va_start(ap, format); 2109151378Snetchild error_work(format, ap); 2110151378Snetchild} 2111151378Snetchild 2112151378Snetchildvoid GenerateOopMap::verify_error(const char *format, ...) { 2113151378Snetchild // We do not distinguish between different types of errors for verification 2114151378Snetchild // errors. Let the verifier give a better message. 2115151378Snetchild const char *msg = "Illegal class file encountered. Try running with -Xverify:all"; 2116151378Snetchild error_work(msg, NULL); 2117151378Snetchild} 2118151378Snetchild 2119151378Snetchild// 2120151378Snetchild// Report result opcodes 2121151378Snetchild// 2122151378Snetchildvoid GenerateOopMap::report_result() { 2123151378Snetchild 2124151378Snetchild if (TraceNewOopMapGeneration) tty->print_cr("Report result pass"); 2125151378Snetchild 2126151378Snetchild // We now want to report the result of the parse 2127151378Snetchild _report_result = true; 2128151378Snetchild 2129151378Snetchild // Prolog code 2130151378Snetchild fill_stackmap_prolog(_gc_points); 2131151378Snetchild 2132151378Snetchild // Mark everything changed, then do one interpretation pass. 2133151378Snetchild for (int i = 0; i<_bb_count; i++) { 2134151378Snetchild if (_basic_blocks[i].is_reachable()) { 2135151378Snetchild _basic_blocks[i].set_changed(true); 2136151378Snetchild interp_bb(&_basic_blocks[i]); 2137151378Snetchild } 2138151378Snetchild } 2139151378Snetchild 2140151378Snetchild // Note: Since we are skipping dead-code when we are reporting results, then 2141151378Snetchild // the no. of encountered gc-points might be fewer than the previously number 2142151378Snetchild // we have counted. (dead-code is a pain - it should be removed before we get here) 2143151378Snetchild fill_stackmap_epilog(); 2144151378Snetchild 2145151378Snetchild // Report initvars 2146151378Snetchild fill_init_vars(_init_vars); 2147151378Snetchild 2148151378Snetchild _report_result = false; 2149151378Snetchild} 2150151378Snetchild 2151151378Snetchildvoid GenerateOopMap::result_for_basicblock(int bci) { 2152151378Snetchild if (TraceNewOopMapGeneration) tty->print_cr("Report result pass for basicblock"); 2153151378Snetchild 2154151378Snetchild // We now want to report the result of the parse 2155151378Snetchild _report_result = true; 2156151378Snetchild 2157151378Snetchild // Find basicblock and report results 2158151378Snetchild BasicBlock* bb = get_basic_block_containing(bci); 2159151378Snetchild assert(bb->is_reachable(), "getting result from unreachable basicblock"); 2160151378Snetchild bb->set_changed(true); 2161151378Snetchild interp_bb(bb); 2162151378Snetchild} 2163151378Snetchild 2164151378Snetchild// 2165151378Snetchild// Conflict handling code 2166151378Snetchild// 2167151378Snetchild 2168151378Snetchildvoid GenerateOopMap::record_refval_conflict(int varNo) { 2169151378Snetchild assert(varNo>=0 && varNo< _max_locals, "index out of range"); 2170151378Snetchild 2171151378Snetchild if (TraceOopMapRewrites) { 2172151378Snetchild tty->print("### Conflict detected (local no: %d)\n", varNo); 2173151378Snetchild } 2174151378Snetchild 2175151378Snetchild if (!_new_var_map) { 2176151378Snetchild _new_var_map = NEW_RESOURCE_ARRAY(int, _max_locals); 2177151378Snetchild for (int k = 0; k < _max_locals; k++) _new_var_map[k] = k; 2178151378Snetchild } 2179151378Snetchild 2180151378Snetchild if ( _new_var_map[varNo] == varNo) { 2181151378Snetchild // Check if max. number of locals has been reached 2182151378Snetchild if (_max_locals + _nof_refval_conflicts >= MAX_LOCAL_VARS) { 2183151378Snetchild report_error("Rewriting exceeded local variable limit"); 2184151378Snetchild return; 2185151378Snetchild } 2186151378Snetchild _new_var_map[varNo] = _max_locals + _nof_refval_conflicts; 2187151378Snetchild _nof_refval_conflicts++; 2188151378Snetchild } 2189151378Snetchild} 2190151378Snetchild 2191151378Snetchildvoid GenerateOopMap::rewrite_refval_conflicts() 2192151378Snetchild{ 2193151378Snetchild // We can get here two ways: Either a rewrite conflict was detected, or 2194151378Snetchild // an uninitialize reference was detected. In the second case, we do not 2195151378Snetchild // do any rewriting, we just want to recompute the reference set with the 2196151378Snetchild // new information 2197151378Snetchild 2198151378Snetchild int nof_conflicts = 0; // Used for debugging only 2199151378Snetchild 2200151378Snetchild if ( _nof_refval_conflicts == 0 ) 2201151378Snetchild return; 2202151378Snetchild 2203151378Snetchild // Check if rewrites are allowed in this parse. 2204151378Snetchild if (!allow_rewrites() && !IgnoreRewrites) { 2205151378Snetchild fatal("Rewriting method not allowed at this stage"); 2206151378Snetchild } 2207151378Snetchild 2208151378Snetchild 2209151378Snetchild // This following flag is to tempoary supress rewrites. The locals that might conflict will 2210151378Snetchild // all be set to contain values. This is UNSAFE - however, until the rewriting has been completely 2211151378Snetchild // tested it is nice to have. 2212151378Snetchild if (IgnoreRewrites) { 2213151378Snetchild if (Verbose) { 2214151378Snetchild tty->print("rewrites suppressed for local no. "); 2215151378Snetchild for (int l = 0; l < _max_locals; l++) { 2216151378Snetchild if (_new_var_map[l] != l) { 2217151378Snetchild tty->print("%d ", l); 2218151378Snetchild vars()[l] = CellTypeState::value; 2219151378Snetchild } 2220151378Snetchild } 2221151378Snetchild tty->cr(); 2222151378Snetchild } 2223151378Snetchild 2224151378Snetchild // That was that... 2225151378Snetchild _new_var_map = NULL; 2226151378Snetchild _nof_refval_conflicts = 0; 2227151378Snetchild _conflict = false; 2228151378Snetchild 2229151378Snetchild return; 2230151378Snetchild } 2231151378Snetchild 2232151378Snetchild // Tracing flag 2233151378Snetchild _did_rewriting = true; 2234151378Snetchild 2235151378Snetchild if (TraceOopMapRewrites) { 2236151378Snetchild tty->print_cr("ref/value conflict for method %s - bytecodes are getting rewritten", method()->name()->as_C_string()); 2237151378Snetchild method()->print(); 2238151378Snetchild method()->print_codes(); 2239151378Snetchild } 2240151378Snetchild 2241151378Snetchild assert(_new_var_map!=NULL, "nothing to rewrite"); 2242151378Snetchild assert(_conflict==true, "We should not be here"); 2243151378Snetchild 2244151378Snetchild compute_ret_adr_at_TOS(); 2245151378Snetchild if (!_got_error) { 2246151378Snetchild for (int k = 0; k < _max_locals && !_got_error; k++) { 2247151378Snetchild if (_new_var_map[k] != k) { 2248151378Snetchild if (TraceOopMapRewrites) { 2249151378Snetchild tty->print_cr("Rewriting: %d -> %d", k, _new_var_map[k]); 2250151378Snetchild } 2251151378Snetchild rewrite_refval_conflict(k, _new_var_map[k]); 2252151378Snetchild if (_got_error) return; 2253151378Snetchild nof_conflicts++; 2254151378Snetchild } 2255151378Snetchild } 2256151378Snetchild } 2257151378Snetchild 2258151378Snetchild assert(nof_conflicts == _nof_refval_conflicts, "sanity check"); 2259151378Snetchild 2260151378Snetchild // Adjust the number of locals 2261151378Snetchild method()->set_max_locals(_max_locals+_nof_refval_conflicts); 2262151378Snetchild _max_locals += _nof_refval_conflicts; 2263151378Snetchild 2264151378Snetchild // That was that... 2265151378Snetchild _new_var_map = NULL; 2266151378Snetchild _nof_refval_conflicts = 0; 2267151378Snetchild} 2268151378Snetchild 2269151378Snetchildvoid GenerateOopMap::rewrite_refval_conflict(int from, int to) { 2270151378Snetchild bool startOver; 2271151378Snetchild do { 2272151378Snetchild // Make sure that the BytecodeStream is constructed in the loop, since 2273151378Snetchild // during rewriting a new method oop is going to be used, and the next time 2274151378Snetchild // around we want to use that. 2275151378Snetchild BytecodeStream bcs(_method); 2276151378Snetchild startOver = false; 2277151378Snetchild 2278151378Snetchild while( bcs.next() >=0 && !startOver && !_got_error) { 2279151378Snetchild startOver = rewrite_refval_conflict_inst(&bcs, from, to); 2280151378Snetchild } 2281151378Snetchild } while (startOver && !_got_error); 2282151378Snetchild} 2283151378Snetchild 2284151378Snetchild/* If the current instruction is one that uses local variable "from" 2285151378Snetchild in a ref way, change it to use "to". There's a subtle reason why we 2286151378Snetchild renumber the ref uses and not the non-ref uses: non-ref uses may be 2287151378Snetchild 2 slots wide (double, long) which would necessitate keeping track of 2288151378Snetchild whether we should add one or two variables to the method. If the change 2289151378Snetchild affected the width of some instruction, returns "TRUE"; otherwise, returns "FALSE". 2290151378Snetchild Another reason for moving ref's value is for solving (addr, ref) conflicts, which 2291151378Snetchild both uses aload/astore methods. 2292151378Snetchild*/ 2293151378Snetchildbool GenerateOopMap::rewrite_refval_conflict_inst(BytecodeStream *itr, int from, int to) { 2294151378Snetchild Bytecodes::Code bc = itr->code(); 2295151378Snetchild int index; 2296151378Snetchild int bci = itr->bci(); 2297151378Snetchild 2298151378Snetchild if (is_aload(itr, &index) && index == from) { 2299151378Snetchild if (TraceOopMapRewrites) { 2300151378Snetchild tty->print_cr("Rewriting aload at bci: %d", bci); 2301151378Snetchild } 2302151378Snetchild return rewrite_load_or_store(itr, Bytecodes::_aload, Bytecodes::_aload_0, to); 2303151378Snetchild } 2304151378Snetchild 2305151378Snetchild if (is_astore(itr, &index) && index == from) { 2306151378Snetchild if (!stack_top_holds_ret_addr(bci)) { 2307151378Snetchild if (TraceOopMapRewrites) { 2308151378Snetchild tty->print_cr("Rewriting astore at bci: %d", bci); 2309151378Snetchild } 2310151378Snetchild return rewrite_load_or_store(itr, Bytecodes::_astore, Bytecodes::_astore_0, to); 2311151378Snetchild } else { 2312151378Snetchild if (TraceOopMapRewrites) { 2313151378Snetchild tty->print_cr("Supress rewriting of astore at bci: %d", bci); 2314151378Snetchild } 2315151378Snetchild } 2316151378Snetchild } 2317151378Snetchild 2318151378Snetchild return false; 2319151378Snetchild} 2320151378Snetchild 2321151378Snetchild// The argument to this method is: 2322151378Snetchild// bc : Current bytecode 2323151378Snetchild// bcN : either _aload or _astore 2324151378Snetchild// bc0 : either _aload_0 or _astore_0 2325151378Snetchildbool GenerateOopMap::rewrite_load_or_store(BytecodeStream *bcs, Bytecodes::Code bcN, Bytecodes::Code bc0, unsigned int varNo) { 2326151378Snetchild assert(bcN == Bytecodes::_astore || bcN == Bytecodes::_aload, "wrong argument (bcN)"); 2327151378Snetchild assert(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0, "wrong argument (bc0)"); 2328151378Snetchild int ilen = Bytecodes::length_at(bcs->bcp()); 2329151378Snetchild int newIlen; 2330151378Snetchild 2331151378Snetchild if (ilen == 4) { 2332151378Snetchild // Original instruction was wide; keep it wide for simplicity 2333151378Snetchild newIlen = 4; 2334151378Snetchild } else if (varNo < 4) 2335151378Snetchild newIlen = 1; 2336151378Snetchild else if (varNo >= 256) 2337151378Snetchild newIlen = 4; 2338151378Snetchild else 2339151378Snetchild newIlen = 2; 2340151378Snetchild 2341151378Snetchild // If we need to relocate in order to patch the byte, we 2342151378Snetchild // do the patching in a temp. buffer, that is passed to the reloc. 2343151378Snetchild // The patching of the bytecode stream is then done by the Relocator. 2344151378Snetchild // This is neccesary, since relocating the instruction at a certain bci, might 2345151378Snetchild // also relocate that instruction, e.g., if a _goto before it gets widen to a _goto_w. 2346151378Snetchild // Hence, we do not know which bci to patch after relocation. 2347151378Snetchild 2348151378Snetchild assert(newIlen <= 4, "sanity check"); 2349151378Snetchild u_char inst_buffer[4]; // Max. instruction size is 4. 2350151378Snetchild address bcp; 2351151378Snetchild 2352151378Snetchild if (newIlen != ilen) { 2353151378Snetchild // Relocation needed do patching in temp. buffer 2354151378Snetchild bcp = (address)inst_buffer; 2355151378Snetchild } else { 2356151378Snetchild bcp = _method->bcp_from(bcs->bci()); 2357151378Snetchild } 2358151378Snetchild 2359151378Snetchild // Patch either directly in methodOop or in temp. buffer 2360151378Snetchild if (newIlen == 1) { 2361151378Snetchild assert(varNo < 4, "varNo too large"); 2362151378Snetchild *bcp = bc0 + varNo; 2363151378Snetchild } else if (newIlen == 2) { 2364151378Snetchild assert(varNo < 256, "2-byte index needed!"); 2365151378Snetchild *(bcp + 0) = bcN; 2366151378Snetchild *(bcp + 1) = varNo; 2367151378Snetchild } else { 2368151378Snetchild assert(newIlen == 4, "Wrong instruction length"); 2369151378Snetchild *(bcp + 0) = Bytecodes::_wide; 2370151378Snetchild *(bcp + 1) = bcN; 2371151378Snetchild Bytes::put_Java_u2(bcp+2, varNo); 2372151378Snetchild } 2373151378Snetchild 2374151378Snetchild if (newIlen != ilen) { 2375151378Snetchild expand_current_instr(bcs->bci(), ilen, newIlen, inst_buffer); 2376151378Snetchild } 2377151378Snetchild 2378151378Snetchild 2379151378Snetchild return (newIlen != ilen); 2380151378Snetchild} 2381151378Snetchild 2382151378Snetchildclass RelocCallback : public RelocatorListener { 2383151378Snetchild private: 2384151378Snetchild GenerateOopMap* _gom; 2385151378Snetchild public: 2386151378Snetchild RelocCallback(GenerateOopMap* gom) { _gom = gom; }; 2387151378Snetchild 2388151378Snetchild // Callback method 2389151378Snetchild virtual void relocated(int bci, int delta, int new_code_length) { 2390151378Snetchild _gom->update_basic_blocks (bci, delta, new_code_length); 2391151378Snetchild _gom->update_ret_adr_at_TOS(bci, delta); 2392151378Snetchild _gom->_rt.update_ret_table (bci, delta); 2393151378Snetchild } 2394151378Snetchild}; 2395151378Snetchild 2396151378Snetchild// Returns true if expanding was succesful. Otherwise, reports an error and 2397151378Snetchild// returns false. 2398151378Snetchildvoid GenerateOopMap::expand_current_instr(int bci, int ilen, int newIlen, u_char inst_buffer[]) { 2399151378Snetchild Thread *THREAD = Thread::current(); // Could really have TRAPS argument. 2400151378Snetchild RelocCallback rcb(this); 2401151378Snetchild Relocator rc(_method, &rcb); 2402151378Snetchild methodHandle m= rc.insert_space_at(bci, newIlen, inst_buffer, THREAD); 2403151378Snetchild if (m.is_null() || HAS_PENDING_EXCEPTION) { 2404151378Snetchild report_error("could not rewrite method - exception occurred or bytecode buffer overflow"); 2405151378Snetchild return; 2406151378Snetchild } 2407151378Snetchild 2408151378Snetchild // Relocator returns a new method oop. 2409151378Snetchild _did_relocation = true; 2410151378Snetchild _method = m; 2411151378Snetchild} 2412151378Snetchild 2413151378Snetchild 2414151378Snetchildbool GenerateOopMap::is_astore(BytecodeStream *itr, int *index) { 2415151378Snetchild Bytecodes::Code bc = itr->code(); 2416151378Snetchild switch(bc) { 2417151378Snetchild case Bytecodes::_astore_0: 2418151378Snetchild case Bytecodes::_astore_1: 2419151378Snetchild case Bytecodes::_astore_2: 2420151378Snetchild case Bytecodes::_astore_3: 2421151378Snetchild *index = bc - Bytecodes::_astore_0; 2422151378Snetchild return true; 2423151378Snetchild case Bytecodes::_astore: 2424151378Snetchild *index = itr->get_index(); 2425151378Snetchild return true; 2426151378Snetchild } 2427151378Snetchild return false; 2428151378Snetchild} 2429151378Snetchild 2430153939Snetchildbool GenerateOopMap::is_aload(BytecodeStream *itr, int *index) { 2431153939Snetchild Bytecodes::Code bc = itr->code(); 2432153939Snetchild switch(bc) { 2433153939Snetchild case Bytecodes::_aload_0: 2434153939Snetchild case Bytecodes::_aload_1: 2435153939Snetchild case Bytecodes::_aload_2: 2436153939Snetchild case Bytecodes::_aload_3: 2437153939Snetchild *index = bc - Bytecodes::_aload_0; 2438153939Snetchild return true; 2439153939Snetchild 2440153939Snetchild case Bytecodes::_aload: 2441153939Snetchild *index = itr->get_index(); 2442153939Snetchild return true; 2443153939Snetchild } 2444153939Snetchild return false; 2445153939Snetchild} 2446153939Snetchild 2447153939Snetchild 2448153939Snetchild// Return true iff the top of the operand stack holds a return address at 2449151378Snetchild// the current instruction 2450151378Snetchildbool GenerateOopMap::stack_top_holds_ret_addr(int bci) { 2451151378Snetchild for(int i = 0; i < _ret_adr_tos->length(); i++) { 2452151378Snetchild if (_ret_adr_tos->at(i) == bci) 2453151378Snetchild return true; 2454151378Snetchild } 2455151378Snetchild 2456151378Snetchild return false; 2457151378Snetchild} 2458151378Snetchild 2459151378Snetchildvoid GenerateOopMap::compute_ret_adr_at_TOS() { 2460151378Snetchild assert(_ret_adr_tos != NULL, "must be initialized"); 2461151378Snetchild _ret_adr_tos->clear(); 2462151378Snetchild 2463151378Snetchild for (int i = 0; i < bb_count(); i++) { 2464151378Snetchild BasicBlock* bb = &_basic_blocks[i]; 2465151378Snetchild 2466151378Snetchild // Make sure to only check basicblocks that are reachable 2467151378Snetchild if (bb->is_reachable()) { 2468151378Snetchild 2469151378Snetchild // For each Basic block we check all instructions 2470151378Snetchild BytecodeStream bcs(_method); 2471151378Snetchild bcs.set_interval(bb->_bci, next_bb_start_pc(bb)); 2472151378Snetchild 2473151378Snetchild restore_state(bb); 2474151378Snetchild 2475151378Snetchild while (bcs.next()>=0 && !_got_error) { 2476151378Snetchild // TDT: should this be is_good_address() ? 2477151378Snetchild if (_stack_top > 0 && stack()[_stack_top-1].is_address()) { 2478151378Snetchild _ret_adr_tos->append(bcs.bci()); 2479151378Snetchild if (TraceNewOopMapGeneration) { 2480151378Snetchild tty->print_cr("Ret_adr TOS at bci: %d", bcs.bci()); 2481151378Snetchild } 2482151378Snetchild } 2483151378Snetchild interp1(&bcs); 2484151378Snetchild } 2485151378Snetchild } 2486151378Snetchild } 2487151378Snetchild} 2488151378Snetchild 2489151378Snetchildvoid GenerateOopMap::update_ret_adr_at_TOS(int bci, int delta) { 2490151378Snetchild for(int i = 0; i < _ret_adr_tos->length(); i++) { 2491151378Snetchild int v = _ret_adr_tos->at(i); 2492151378Snetchild if (v > bci) _ret_adr_tos->at_put(i, v + delta); 2493151378Snetchild } 2494151378Snetchild} 2495151378Snetchild 2496151378Snetchild// =================================================================== 2497151378Snetchild 2498151378Snetchild#ifndef PRODUCT 2499151378Snetchildint ResolveOopMapConflicts::_nof_invocations = 0; 2500151378Snetchildint ResolveOopMapConflicts::_nof_rewrites = 0; 2501151378Snetchildint ResolveOopMapConflicts::_nof_relocations = 0; 2502151378Snetchild#endif 2503151378Snetchild 2504151378SnetchildmethodHandle ResolveOopMapConflicts::do_potential_rewrite(TRAPS) { 2505151378Snetchild compute_map(CHECK_(methodHandle())); 2506151378Snetchild 2507151378Snetchild#ifndef PRODUCT 2508151378Snetchild // Tracking and statistics 2509151378Snetchild if (PrintRewrites) { 2510151378Snetchild _nof_invocations++; 2511151378Snetchild if (did_rewriting()) { 2512151378Snetchild _nof_rewrites++; 2513151378Snetchild if (did_relocation()) _nof_relocations++; 2514151378Snetchild tty->print("Method was rewritten %s: ", (did_relocation()) ? "and relocated" : ""); 2515151378Snetchild method()->print_value(); tty->cr(); 2516151378Snetchild tty->print_cr("Cand.: %d rewrts: %d (%d%%) reloc.: %d (%d%%)", 2517151378Snetchild _nof_invocations, 2518153939Snetchild _nof_rewrites, (_nof_rewrites * 100) / _nof_invocations, 2519153939Snetchild _nof_relocations, (_nof_relocations * 100) / _nof_invocations); 2520153939Snetchild } 2521153939Snetchild } 2522153939Snetchild#endif 2523153939Snetchild return methodHandle(THREAD, method()); 2524153939Snetchild} 2525153939Snetchild