Fri, 16 Aug 2013 14:11:40 -0700
8021898: Broken JIT compiler optimization for loop unswitching
Summary: fix method clone_projs() to clone all related MachProj nodes.
Reviewed-by: roland, adlertz
1.1 --- a/src/share/vm/opto/chaitin.cpp Fri Aug 16 13:39:26 2013 -0400 1.2 +++ b/src/share/vm/opto/chaitin.cpp Fri Aug 16 14:11:40 2013 -0700 1.3 @@ -287,21 +287,26 @@ 1.4 } 1.5 1.6 1.7 -bool PhaseChaitin::clone_projs_shared(Block *b, uint idx, Node *con, Node *copy, uint max_lrg_id) { 1.8 - Block* bcon = _cfg.get_block_for_node(con); 1.9 - uint cindex = bcon->find_node(con); 1.10 - Node *con_next = bcon->_nodes[cindex+1]; 1.11 - if (con_next->in(0) != con || !con_next->is_MachProj()) { 1.12 - return false; // No MachProj's follow 1.13 +int PhaseChaitin::clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id) { 1.14 + assert(b->find_node(copy) == (idx - 1), "incorrect insert index for copy kill projections"); 1.15 + DEBUG_ONLY( Block* borig = _cfg.get_block_for_node(orig); ) 1.16 + int found_projs = 0; 1.17 + uint cnt = orig->outcnt(); 1.18 + for (uint i = 0; i < cnt; i++) { 1.19 + Node* proj = orig->raw_out(i); 1.20 + if (proj->is_MachProj()) { 1.21 + assert(proj->outcnt() == 0, "only kill projections are expected here"); 1.22 + assert(_cfg.get_block_for_node(proj) == borig, "incorrect block for kill projections"); 1.23 + found_projs++; 1.24 + // Copy kill projections after the cloned node 1.25 + Node* kills = proj->clone(); 1.26 + kills->set_req(0, copy); 1.27 + b->_nodes.insert(idx++, kills); 1.28 + _cfg.map_node_to_block(kills, b); 1.29 + new_lrg(kills, max_lrg_id++); 1.30 + } 1.31 } 1.32 - 1.33 - // Copy kills after the cloned constant 1.34 - Node *kills = con_next->clone(); 1.35 - kills->set_req(0, copy); 1.36 - b->_nodes.insert(idx, kills); 1.37 - _cfg.map_node_to_block(kills, b); 1.38 - new_lrg(kills, max_lrg_id); 1.39 - return true; 1.40 + return found_projs; 1.41 } 1.42 1.43 // Renumber the live ranges to compact them. Makes the IFG smaller.
2.1 --- a/src/share/vm/opto/chaitin.hpp Fri Aug 16 13:39:26 2013 -0400 2.2 +++ b/src/share/vm/opto/chaitin.hpp Fri Aug 16 14:11:40 2013 -0700 2.3 @@ -412,33 +412,22 @@ 2.4 uint split_DEF( Node *def, Block *b, int loc, uint max, Node **Reachblock, Node **debug_defs, GrowableArray<uint> splits, int slidx ); 2.5 uint split_USE( Node *def, Block *b, Node *use, uint useidx, uint max, bool def_down, bool cisc_sp, GrowableArray<uint> splits, int slidx ); 2.6 2.7 - bool clone_projs(Block *b, uint idx, Node *con, Node *copy, LiveRangeMap &lrg_map) { 2.8 - bool found_projs = clone_projs_shared(b, idx, con, copy, lrg_map.max_lrg_id()); 2.9 - 2.10 - if(found_projs) { 2.11 - uint max_lrg_id = lrg_map.max_lrg_id(); 2.12 - lrg_map.set_max_lrg_id(max_lrg_id + 1); 2.13 - } 2.14 - 2.15 - return found_projs; 2.16 - } 2.17 - 2.18 //------------------------------clone_projs------------------------------------ 2.19 // After cloning some rematerialized instruction, clone any MachProj's that 2.20 // follow it. Example: Intel zero is XOR, kills flags. Sparc FP constants 2.21 // use G3 as an address temp. 2.22 - bool clone_projs(Block *b, uint idx, Node *con, Node *copy, uint &max_lrg_id) { 2.23 - bool found_projs = clone_projs_shared(b, idx, con, copy, max_lrg_id); 2.24 + int clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id); 2.25 2.26 - if(found_projs) { 2.27 - max_lrg_id++; 2.28 + int clone_projs(Block* b, uint idx, Node* orig, Node* copy, LiveRangeMap& lrg_map) { 2.29 + uint max_lrg_id = lrg_map.max_lrg_id(); 2.30 + int found_projs = clone_projs(b, idx, orig, copy, max_lrg_id); 2.31 + if (found_projs > 0) { 2.32 + // max_lrg_id is updated during call above 2.33 + lrg_map.set_max_lrg_id(max_lrg_id); 2.34 } 2.35 - 2.36 return found_projs; 2.37 } 2.38 2.39 - bool clone_projs_shared(Block *b, uint idx, Node *con, Node *copy, uint max_lrg_id); 2.40 - 2.41 Node *split_Rematerialize(Node *def, Block *b, uint insidx, uint &maxlrg, GrowableArray<uint> splits, 2.42 int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru); 2.43 // True if lidx is used before any real register is def'd in the block
3.1 --- a/src/share/vm/opto/coalesce.cpp Fri Aug 16 13:39:26 2013 -0400 3.2 +++ b/src/share/vm/opto/coalesce.cpp Fri Aug 16 14:11:40 2013 -0700 3.3 @@ -322,9 +322,7 @@ 3.4 copy = m->clone(); 3.5 // Insert the copy in the basic block, just before us 3.6 b->_nodes.insert(l++, copy); 3.7 - if(_phc.clone_projs(b, l, m, copy, _phc._lrg_map)) { 3.8 - l++; 3.9 - } 3.10 + l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map); 3.11 } else { 3.12 const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()]; 3.13 copy = new (C) MachSpillCopyNode(m, *rm, *rm);
4.1 --- a/src/share/vm/opto/reg_split.cpp Fri Aug 16 13:39:26 2013 -0400 4.2 +++ b/src/share/vm/opto/reg_split.cpp Fri Aug 16 14:11:40 2013 -0700 4.3 @@ -397,10 +397,15 @@ 4.4 #endif 4.5 // See if the cloned def kills any flags, and copy those kills as well 4.6 uint i = insidx+1; 4.7 - if( clone_projs( b, i, def, spill, maxlrg) ) { 4.8 + int found_projs = clone_projs( b, i, def, spill, maxlrg); 4.9 + if (found_projs > 0) { 4.10 // Adjust the point where we go hi-pressure 4.11 - if( i <= b->_ihrp_index ) b->_ihrp_index++; 4.12 - if( i <= b->_fhrp_index ) b->_fhrp_index++; 4.13 + if (i <= b->_ihrp_index) { 4.14 + b->_ihrp_index += found_projs; 4.15 + } 4.16 + if (i <= b->_fhrp_index) { 4.17 + b->_fhrp_index += found_projs; 4.18 + } 4.19 } 4.20 4.21 return spill;
5.1 --- a/src/share/vm/runtime/frame.cpp Fri Aug 16 13:39:26 2013 -0400 5.2 +++ b/src/share/vm/runtime/frame.cpp Fri Aug 16 14:11:40 2013 -0700 5.3 @@ -23,6 +23,7 @@ 5.4 */ 5.5 5.6 #include "precompiled.hpp" 5.7 +#include "compiler/abstractCompiler.hpp" 5.8 #include "compiler/disassembler.hpp" 5.9 #include "gc_interface/collectedHeap.inline.hpp" 5.10 #include "interpreter/interpreter.hpp" 5.11 @@ -559,7 +560,7 @@ 5.12 5.13 st->print("%s frame (sp=" INTPTR_FORMAT " unextended sp=" INTPTR_FORMAT, print_name(), sp(), unextended_sp()); 5.14 if (sp() != NULL) 5.15 - st->print(", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), pc()); 5.16 + st->print(", fp=" INTPTR_FORMAT ", real_fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), real_fp(), pc()); 5.17 5.18 if (StubRoutines::contains(pc())) { 5.19 st->print_cr(")"); 5.20 @@ -720,11 +721,14 @@ 5.21 } else if (_cb->is_buffer_blob()) { 5.22 st->print("v ~BufferBlob::%s", ((BufferBlob *)_cb)->name()); 5.23 } else if (_cb->is_nmethod()) { 5.24 - Method* m = ((nmethod *)_cb)->method(); 5.25 + nmethod* nm = (nmethod*)_cb; 5.26 + Method* m = nm->method(); 5.27 if (m != NULL) { 5.28 m->name_and_sig_as_C_string(buf, buflen); 5.29 - st->print("J %s @ " PTR_FORMAT " [" PTR_FORMAT "+" SIZE_FORMAT "]", 5.30 - buf, _pc, _cb->code_begin(), _pc - _cb->code_begin()); 5.31 + st->print("J %d%s %s %s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+0x%x]", 5.32 + nm->compile_id(), (nm->is_osr_method() ? "%" : ""), 5.33 + ((nm->compiler() != NULL) ? nm->compiler()->name() : ""), 5.34 + buf, m->code_size(), _pc, _cb->code_begin(), _pc - _cb->code_begin()); 5.35 } else { 5.36 st->print("J " PTR_FORMAT, pc()); 5.37 }
6.1 --- a/src/share/vm/utilities/vmError.cpp Fri Aug 16 13:39:26 2013 -0400 6.2 +++ b/src/share/vm/utilities/vmError.cpp Fri Aug 16 14:11:40 2013 -0700 6.3 @@ -586,6 +586,13 @@ 6.4 while (count++ < StackPrintLimit) { 6.5 fr.print_on_error(st, buf, sizeof(buf)); 6.6 st->cr(); 6.7 + // Compiled code may use EBP register on x86 so it looks like 6.8 + // non-walkable C frame. Use frame.sender() for java frames. 6.9 + if (_thread && _thread->is_Java_thread() && fr.is_java_frame()) { 6.10 + RegisterMap map((JavaThread*)_thread, false); // No update 6.11 + fr = fr.sender(&map); 6.12 + continue; 6.13 + } 6.14 if (os::is_first_C_frame(&fr)) break; 6.15 fr = os::get_sender_for_C_frame(&fr); 6.16 }