# HG changeset patch # User kvn # Date 1376687500 25200 # Node ID 3aa9ca404965358aea9e395188c2efeeab9ce075 # Parent 217b3e5dbfdeb69e1d0c7060d3e21d4e6b2a958f 8021898: Broken JIT compiler optimization for loop unswitching Summary: fix method clone_projs() to clone all related MachProj nodes. Reviewed-by: roland, adlertz diff -r 217b3e5dbfde -r 3aa9ca404965 hotspot/src/share/vm/opto/chaitin.cpp --- a/hotspot/src/share/vm/opto/chaitin.cpp Fri Aug 16 13:39:26 2013 -0400 +++ b/hotspot/src/share/vm/opto/chaitin.cpp Fri Aug 16 14:11:40 2013 -0700 @@ -287,21 +287,26 @@ } -bool PhaseChaitin::clone_projs_shared(Block *b, uint idx, Node *con, Node *copy, uint max_lrg_id) { - Block* bcon = _cfg.get_block_for_node(con); - uint cindex = bcon->find_node(con); - Node *con_next = bcon->_nodes[cindex+1]; - if (con_next->in(0) != con || !con_next->is_MachProj()) { - return false; // No MachProj's follow +int PhaseChaitin::clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id) { + assert(b->find_node(copy) == (idx - 1), "incorrect insert index for copy kill projections"); + DEBUG_ONLY( Block* borig = _cfg.get_block_for_node(orig); ) + int found_projs = 0; + uint cnt = orig->outcnt(); + for (uint i = 0; i < cnt; i++) { + Node* proj = orig->raw_out(i); + if (proj->is_MachProj()) { + assert(proj->outcnt() == 0, "only kill projections are expected here"); + assert(_cfg.get_block_for_node(proj) == borig, "incorrect block for kill projections"); + found_projs++; + // Copy kill projections after the cloned node + Node* kills = proj->clone(); + kills->set_req(0, copy); + b->_nodes.insert(idx++, kills); + _cfg.map_node_to_block(kills, b); + new_lrg(kills, max_lrg_id++); + } } - - // Copy kills after the cloned constant - Node *kills = con_next->clone(); - kills->set_req(0, copy); - b->_nodes.insert(idx, kills); - _cfg.map_node_to_block(kills, b); - new_lrg(kills, max_lrg_id); - return true; + return found_projs; } // Renumber the live ranges to compact them. Makes the IFG smaller. diff -r 217b3e5dbfde -r 3aa9ca404965 hotspot/src/share/vm/opto/chaitin.hpp --- a/hotspot/src/share/vm/opto/chaitin.hpp Fri Aug 16 13:39:26 2013 -0400 +++ b/hotspot/src/share/vm/opto/chaitin.hpp Fri Aug 16 14:11:40 2013 -0700 @@ -412,33 +412,22 @@ uint split_DEF( Node *def, Block *b, int loc, uint max, Node **Reachblock, Node **debug_defs, GrowableArray splits, int slidx ); uint split_USE( Node *def, Block *b, Node *use, uint useidx, uint max, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ); - bool clone_projs(Block *b, uint idx, Node *con, Node *copy, LiveRangeMap &lrg_map) { - bool found_projs = clone_projs_shared(b, idx, con, copy, lrg_map.max_lrg_id()); - - if(found_projs) { - uint max_lrg_id = lrg_map.max_lrg_id(); - lrg_map.set_max_lrg_id(max_lrg_id + 1); - } - - return found_projs; - } - //------------------------------clone_projs------------------------------------ // After cloning some rematerialized instruction, clone any MachProj's that // follow it. Example: Intel zero is XOR, kills flags. Sparc FP constants // use G3 as an address temp. - bool clone_projs(Block *b, uint idx, Node *con, Node *copy, uint &max_lrg_id) { - bool found_projs = clone_projs_shared(b, idx, con, copy, max_lrg_id); + int clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id); - if(found_projs) { - max_lrg_id++; + int clone_projs(Block* b, uint idx, Node* orig, Node* copy, LiveRangeMap& lrg_map) { + uint max_lrg_id = lrg_map.max_lrg_id(); + int found_projs = clone_projs(b, idx, orig, copy, max_lrg_id); + if (found_projs > 0) { + // max_lrg_id is updated during call above + lrg_map.set_max_lrg_id(max_lrg_id); } - return found_projs; } - bool clone_projs_shared(Block *b, uint idx, Node *con, Node *copy, uint max_lrg_id); - Node *split_Rematerialize(Node *def, Block *b, uint insidx, uint &maxlrg, GrowableArray splits, int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru); // True if lidx is used before any real register is def'd in the block diff -r 217b3e5dbfde -r 3aa9ca404965 hotspot/src/share/vm/opto/coalesce.cpp --- a/hotspot/src/share/vm/opto/coalesce.cpp Fri Aug 16 13:39:26 2013 -0400 +++ b/hotspot/src/share/vm/opto/coalesce.cpp Fri Aug 16 14:11:40 2013 -0700 @@ -322,9 +322,7 @@ copy = m->clone(); // Insert the copy in the basic block, just before us b->_nodes.insert(l++, copy); - if(_phc.clone_projs(b, l, m, copy, _phc._lrg_map)) { - l++; - } + l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map); } else { const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()]; copy = new (C) MachSpillCopyNode(m, *rm, *rm); diff -r 217b3e5dbfde -r 3aa9ca404965 hotspot/src/share/vm/opto/reg_split.cpp --- a/hotspot/src/share/vm/opto/reg_split.cpp Fri Aug 16 13:39:26 2013 -0400 +++ b/hotspot/src/share/vm/opto/reg_split.cpp Fri Aug 16 14:11:40 2013 -0700 @@ -397,10 +397,15 @@ #endif // See if the cloned def kills any flags, and copy those kills as well uint i = insidx+1; - if( clone_projs( b, i, def, spill, maxlrg) ) { + int found_projs = clone_projs( b, i, def, spill, maxlrg); + if (found_projs > 0) { // Adjust the point where we go hi-pressure - if( i <= b->_ihrp_index ) b->_ihrp_index++; - if( i <= b->_fhrp_index ) b->_fhrp_index++; + if (i <= b->_ihrp_index) { + b->_ihrp_index += found_projs; + } + if (i <= b->_fhrp_index) { + b->_fhrp_index += found_projs; + } } return spill; diff -r 217b3e5dbfde -r 3aa9ca404965 hotspot/src/share/vm/runtime/frame.cpp --- a/hotspot/src/share/vm/runtime/frame.cpp Fri Aug 16 13:39:26 2013 -0400 +++ b/hotspot/src/share/vm/runtime/frame.cpp Fri Aug 16 14:11:40 2013 -0700 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "compiler/abstractCompiler.hpp" #include "compiler/disassembler.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" @@ -559,7 +560,7 @@ st->print("%s frame (sp=" INTPTR_FORMAT " unextended sp=" INTPTR_FORMAT, print_name(), sp(), unextended_sp()); if (sp() != NULL) - st->print(", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), pc()); + st->print(", fp=" INTPTR_FORMAT ", real_fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), real_fp(), pc()); if (StubRoutines::contains(pc())) { st->print_cr(")"); @@ -720,11 +721,14 @@ } else if (_cb->is_buffer_blob()) { st->print("v ~BufferBlob::%s", ((BufferBlob *)_cb)->name()); } else if (_cb->is_nmethod()) { - Method* m = ((nmethod *)_cb)->method(); + nmethod* nm = (nmethod*)_cb; + Method* m = nm->method(); if (m != NULL) { m->name_and_sig_as_C_string(buf, buflen); - st->print("J %s @ " PTR_FORMAT " [" PTR_FORMAT "+" SIZE_FORMAT "]", - buf, _pc, _cb->code_begin(), _pc - _cb->code_begin()); + st->print("J %d%s %s %s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+0x%x]", + nm->compile_id(), (nm->is_osr_method() ? "%" : ""), + ((nm->compiler() != NULL) ? nm->compiler()->name() : ""), + buf, m->code_size(), _pc, _cb->code_begin(), _pc - _cb->code_begin()); } else { st->print("J " PTR_FORMAT, pc()); } diff -r 217b3e5dbfde -r 3aa9ca404965 hotspot/src/share/vm/utilities/vmError.cpp --- a/hotspot/src/share/vm/utilities/vmError.cpp Fri Aug 16 13:39:26 2013 -0400 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Fri Aug 16 14:11:40 2013 -0700 @@ -586,6 +586,13 @@ while (count++ < StackPrintLimit) { fr.print_on_error(st, buf, sizeof(buf)); st->cr(); + // Compiled code may use EBP register on x86 so it looks like + // non-walkable C frame. Use frame.sender() for java frames. + if (_thread && _thread->is_Java_thread() && fr.is_java_frame()) { + RegisterMap map((JavaThread*)_thread, false); // No update + fr = fr.sender(&map); + continue; + } if (os::is_first_C_frame(&fr)) break; fr = os::get_sender_for_C_frame(&fr); }