Sun, 27 Mar 2011 00:00:14 -0700
7024475: loop doesn't terminate when compiled
Reviewed-by: kvn
1.1 --- a/src/share/vm/compiler/compileBroker.cpp Sat Mar 26 08:31:45 2011 -0700 1.2 +++ b/src/share/vm/compiler/compileBroker.cpp Sun Mar 27 00:00:14 2011 -0700 1.3 @@ -874,6 +874,14 @@ 1.4 return; 1.5 } 1.6 1.7 +#ifndef PRODUCT 1.8 + if (osr_bci != -1 && !FLAG_IS_DEFAULT(OSROnlyBCI)) { 1.9 + if ((OSROnlyBCI > 0) ? (OSROnlyBCI != osr_bci) : (-OSROnlyBCI == osr_bci)) { 1.10 + // Positive OSROnlyBCI means only compile that bci. Negative means don't compile that BCI. 1.11 + return; 1.12 + } 1.13 + } 1.14 +#endif 1.15 1.16 // If this method is already in the compile queue, then 1.17 // we do not block the current thread.
2.1 --- a/src/share/vm/opto/idealGraphPrinter.cpp Sat Mar 26 08:31:45 2011 -0700 2.2 +++ b/src/share/vm/opto/idealGraphPrinter.cpp Sun Mar 27 00:00:14 2011 -0700 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -599,11 +599,35 @@ 2.11 2.12 if (caller != NULL) { 2.13 stringStream bciStream; 2.14 + ciMethod* last = NULL; 2.15 + int last_bci; 2.16 while(caller) { 2.17 + if (caller->has_method()) { 2.18 + last = caller->method(); 2.19 + last_bci = caller->bci(); 2.20 + } 2.21 bciStream.print("%d ", caller->bci()); 2.22 caller = caller->caller(); 2.23 } 2.24 print_prop("bci", bciStream.as_string()); 2.25 + if (last != NULL && last->has_linenumber_table() && last_bci >= 0) { 2.26 + print_prop("line", last->line_number_from_bci(last_bci)); 2.27 + } 2.28 + } 2.29 + 2.30 + if (node->debug_orig() != NULL) { 2.31 + stringStream dorigStream; 2.32 + Node* dorig = node->debug_orig(); 2.33 + if (dorig) { 2.34 + dorigStream.print("%d ", dorig->_idx); 2.35 + Node* first = dorig; 2.36 + dorig = first->debug_orig(); 2.37 + while (dorig && dorig != first) { 2.38 + dorigStream.print("%d ", dorig->_idx); 2.39 + dorig = dorig->debug_orig(); 2.40 + } 2.41 + } 2.42 + print_prop("debug_orig", dorigStream.as_string()); 2.43 } 2.44 2.45 if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { 2.46 @@ -628,6 +652,17 @@ 2.47 GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); 2.48 nodeStack.push(start); 2.49 visited.test_set(start->_idx); 2.50 + if (C->cfg() != NULL) { 2.51 + // once we have a CFG there are some nodes that aren't really 2.52 + // reachable but are in the CFG so add them here. 2.53 + for (uint i = 0; i < C->cfg()->_blocks.size(); i++) { 2.54 + Block *b = C->cfg()->_blocks[i]; 2.55 + for (uint s = 0; s < b->_nodes.size(); s++) { 2.56 + nodeStack.push(b->_nodes[s]); 2.57 + } 2.58 + } 2.59 + } 2.60 + 2.61 while(nodeStack.length() > 0) { 2.62 2.63 Node *n = nodeStack.pop(); 2.64 @@ -686,16 +721,23 @@ 2.65 end_head(); 2.66 2.67 head(SUCCESSORS_ELEMENT); 2.68 - for (uint s = 0; s < C->cfg()->_blocks[i]->_num_succs; s++) { 2.69 + for (uint s = 0; s < b->_num_succs; s++) { 2.70 begin_elem(SUCCESSOR_ELEMENT); 2.71 print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order); 2.72 end_elem(); 2.73 } 2.74 tail(SUCCESSORS_ELEMENT); 2.75 2.76 + head(NODES_ELEMENT); 2.77 + for (uint s = 0; s < b->_nodes.size(); s++) { 2.78 + begin_elem(NODE_ELEMENT); 2.79 + print_attr(NODE_ID_PROPERTY, get_node_id(b->_nodes[s])); 2.80 + end_elem(); 2.81 + } 2.82 + tail(NODES_ELEMENT); 2.83 + 2.84 tail(BLOCK_ELEMENT); 2.85 } 2.86 - 2.87 tail(CONTROL_FLOW_ELEMENT); 2.88 } 2.89 tail(GRAPH_ELEMENT);
3.1 --- a/src/share/vm/opto/idealGraphPrinter.hpp Sat Mar 26 08:31:45 2011 -0700 3.2 +++ b/src/share/vm/opto/idealGraphPrinter.hpp Sun Mar 27 00:00:14 2011 -0700 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -45,15 +45,6 @@ 3.11 { 3.12 private: 3.13 3.14 - enum State 3.15 - { 3.16 - Invalid, 3.17 - Valid, 3.18 - New 3.19 - }; 3.20 - 3.21 -private: 3.22 - 3.23 static const char *INDENT; 3.24 static const char *TOP_ELEMENT; 3.25 static const char *GROUP_ELEMENT;
4.1 --- a/src/share/vm/opto/loopTransform.cpp Sat Mar 26 08:31:45 2011 -0700 4.2 +++ b/src/share/vm/opto/loopTransform.cpp Sun Mar 27 00:00:14 2011 -0700 4.3 @@ -1608,15 +1608,7 @@ 4.4 return false; // Malformed loop 4.5 if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) 4.6 return false; // Infinite loop 4.7 -#ifndef PRODUCT 4.8 - if (PrintOpto) { 4.9 - tty->print("Removing empty loop"); 4.10 - this->dump_head(); 4.11 - } else if (TraceLoopOpts) { 4.12 - tty->print("Empty "); 4.13 - this->dump_head(); 4.14 - } 4.15 -#endif 4.16 + 4.17 #ifdef ASSERT 4.18 // Ensure only one phi which is the iv. 4.19 Node* iv = NULL; 4.20 @@ -1629,6 +1621,43 @@ 4.21 } 4.22 assert(iv == cl->phi(), "Wrong phi" ); 4.23 #endif 4.24 + 4.25 + // main and post loops have explicitly created zero trip guard 4.26 + bool needs_guard = !cl->is_main_loop() && !cl->is_post_loop(); 4.27 + if (needs_guard) { 4.28 + // Check for an obvious zero trip guard. 4.29 + Node* inctrl = cl->in(LoopNode::EntryControl); 4.30 + if (inctrl->Opcode() == Op_IfTrue) { 4.31 + // The test should look like just the backedge of a CountedLoop 4.32 + Node* iff = inctrl->in(0); 4.33 + if (iff->is_If()) { 4.34 + Node* bol = iff->in(1); 4.35 + if (bol->is_Bool() && bol->as_Bool()->_test._test == cl->loopexit()->test_trip()) { 4.36 + Node* cmp = bol->in(1); 4.37 + if (cmp->is_Cmp() && cmp->in(1) == cl->init_trip() && cmp->in(2) == cl->limit()) { 4.38 + needs_guard = false; 4.39 + } 4.40 + } 4.41 + } 4.42 + } 4.43 + } 4.44 + 4.45 +#ifndef PRODUCT 4.46 + if (PrintOpto) { 4.47 + tty->print("Removing empty loop with%s zero trip guard", needs_guard ? "out" : ""); 4.48 + this->dump_head(); 4.49 + } else if (TraceLoopOpts) { 4.50 + tty->print("Empty with%s zero trip guard ", needs_guard ? "out" : ""); 4.51 + this->dump_head(); 4.52 + } 4.53 +#endif 4.54 + 4.55 + if (needs_guard) { 4.56 + // Peel the loop to ensure there's a zero trip guard 4.57 + Node_List old_new; 4.58 + phase->do_peeling(this, old_new); 4.59 + } 4.60 + 4.61 // Replace the phi at loop head with the final value of the last 4.62 // iteration. Then the CountedLoopEnd will collapse (backedge never 4.63 // taken) and all loop-invariant uses of the exit values will be correct.
5.1 --- a/src/share/vm/opto/loopnode.cpp Sat Mar 26 08:31:45 2011 -0700 5.2 +++ b/src/share/vm/opto/loopnode.cpp Sun Mar 27 00:00:14 2011 -0700 5.3 @@ -1064,8 +1064,6 @@ 5.4 // Cache parts in locals for easy 5.5 PhaseIterGVN &igvn = phase->_igvn; 5.6 5.7 - phase->C->print_method("Before beautify loops", 3); 5.8 - 5.9 igvn.hash_delete(_head); // Yank from hash before hacking edges 5.10 5.11 // Check for multiple fall-in paths. Peel off a landing pad if need be. 5.12 @@ -1547,6 +1545,7 @@ 5.13 ResourceMark rm; 5.14 5.15 int old_progress = C->major_progress(); 5.16 + uint orig_worklist_size = _igvn._worklist.size(); 5.17 5.18 // Reset major-progress flag for the driver's heuristics 5.19 C->clear_major_progress(); 5.20 @@ -1610,6 +1609,7 @@ 5.21 // Split shared headers and insert loop landing pads. 5.22 // Do not bother doing this on the Root loop of course. 5.23 if( !_verify_me && !_verify_only && _ltree_root->_child ) { 5.24 + C->print_method("Before beautify loops", 3); 5.25 if( _ltree_root->_child->beautify_loops( this ) ) { 5.26 // Re-build loop tree! 5.27 _ltree_root->_child = NULL; 5.28 @@ -1694,7 +1694,7 @@ 5.29 for (int i = 0; i < old_progress; i++) 5.30 C->set_major_progress(); 5.31 assert(C->unique() == unique, "verification mode made Nodes? ? ?"); 5.32 - assert(_igvn._worklist.size() == 0, "shouldn't push anything"); 5.33 + assert(_igvn._worklist.size() == orig_worklist_size, "shouldn't push anything"); 5.34 return; 5.35 } 5.36
6.1 --- a/src/share/vm/opto/node.cpp Sat Mar 26 08:31:45 2011 -0700 6.2 +++ b/src/share/vm/opto/node.cpp Sun Mar 27 00:00:14 2011 -0700 6.3 @@ -1373,12 +1373,12 @@ 6.4 //------------------------------find------------------------------------------ 6.5 // Find a neighbor of this Node with the given _idx 6.6 // If idx is negative, find its absolute value, following both _in and _out. 6.7 -static void find_recur( Node* &result, Node *n, int idx, bool only_ctrl, 6.8 - VectorSet &old_space, VectorSet &new_space ) { 6.9 +static void find_recur(Compile* C, Node* &result, Node *n, int idx, bool only_ctrl, 6.10 + VectorSet* old_space, VectorSet* new_space ) { 6.11 int node_idx = (idx >= 0) ? idx : -idx; 6.12 if (NotANode(n)) return; // Gracefully handle NULL, -1, 0xabababab, etc. 6.13 - // Contained in new_space or old_space? 6.14 - VectorSet *v = Compile::current()->node_arena()->contains(n) ? &new_space : &old_space; 6.15 + // Contained in new_space or old_space? Check old_arena first since it's mostly empty. 6.16 + VectorSet *v = C->old_arena()->contains(n) ? old_space : new_space; 6.17 if( v->test(n->_idx) ) return; 6.18 if( (int)n->_idx == node_idx 6.19 debug_only(|| n->debug_idx() == node_idx) ) { 6.20 @@ -1390,19 +1390,23 @@ 6.21 v->set(n->_idx); 6.22 for( uint i=0; i<n->len(); i++ ) { 6.23 if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue; 6.24 - find_recur( result, n->in(i), idx, only_ctrl, old_space, new_space ); 6.25 + find_recur(C, result, n->in(i), idx, only_ctrl, old_space, new_space ); 6.26 } 6.27 // Search along forward edges also: 6.28 if (idx < 0 && !only_ctrl) { 6.29 for( uint j=0; j<n->outcnt(); j++ ) { 6.30 - find_recur( result, n->raw_out(j), idx, only_ctrl, old_space, new_space ); 6.31 + find_recur(C, result, n->raw_out(j), idx, only_ctrl, old_space, new_space ); 6.32 } 6.33 } 6.34 #ifdef ASSERT 6.35 - // Search along debug_orig edges last: 6.36 - for (Node* orig = n->debug_orig(); orig != NULL && n != orig; orig = orig->debug_orig()) { 6.37 - if (NotANode(orig)) break; 6.38 - find_recur( result, orig, idx, only_ctrl, old_space, new_space ); 6.39 + // Search along debug_orig edges last, checking for cycles 6.40 + Node* orig = n->debug_orig(); 6.41 + if (orig != NULL) { 6.42 + do { 6.43 + if (NotANode(orig)) break; 6.44 + find_recur(C, result, orig, idx, only_ctrl, old_space, new_space ); 6.45 + orig = orig->debug_orig(); 6.46 + } while (orig != NULL && orig != n->debug_orig()); 6.47 } 6.48 #endif //ASSERT 6.49 } 6.50 @@ -1417,7 +1421,7 @@ 6.51 ResourceArea *area = Thread::current()->resource_area(); 6.52 VectorSet old_space(area), new_space(area); 6.53 Node* result = NULL; 6.54 - find_recur( result, (Node*) this, idx, false, old_space, new_space ); 6.55 + find_recur(Compile::current(), result, (Node*) this, idx, false, &old_space, &new_space ); 6.56 return result; 6.57 } 6.58 6.59 @@ -1427,7 +1431,7 @@ 6.60 ResourceArea *area = Thread::current()->resource_area(); 6.61 VectorSet old_space(area), new_space(area); 6.62 Node* result = NULL; 6.63 - find_recur( result, (Node*) this, idx, true, old_space, new_space ); 6.64 + find_recur(Compile::current(), result, (Node*) this, idx, true, &old_space, &new_space ); 6.65 return result; 6.66 } 6.67 #endif
7.1 --- a/src/share/vm/runtime/globals.hpp Sat Mar 26 08:31:45 2011 -0700 7.2 +++ b/src/share/vm/runtime/globals.hpp Sun Mar 27 00:00:14 2011 -0700 7.3 @@ -2377,6 +2377,9 @@ 7.4 develop(intx, CICloneLoopTestLimit, 100, \ 7.5 "size limit for blocks heuristically cloned in ciTypeFlow") \ 7.6 \ 7.7 + develop(intx, OSROnlyBCI, -1, \ 7.8 + "OSR only at this bci. Negative values mean exclude that bci") \ 7.9 + \ 7.10 /* temp diagnostics */ \ 7.11 \ 7.12 diagnostic(bool, TraceRedundantCompiles, false, \
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/compiler/7024475/Test7024475.java Sun Mar 27 00:00:14 2011 -0700 8.3 @@ -0,0 +1,71 @@ 8.4 +/* 8.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + * 8.26 + */ 8.27 + 8.28 +/** 8.29 + * @test 8.30 + * @bug 7024475 8.31 + * @summary loop doesn't terminate when compiled 8.32 + * 8.33 + * @run main Test7024475 8.34 + */ 8.35 + 8.36 +public class Test7024475 { 8.37 + 8.38 + static int i; 8.39 + static int x1; 8.40 + static int[] bucket_B; 8.41 + 8.42 + static void test(Test7024475 test, int i, int c0, int j, int c1) { 8.43 + for (;;) { 8.44 + if (c1 > c0) { 8.45 + if (c0 > 253) { 8.46 + throw new InternalError("c0 = " + c0); 8.47 + } 8.48 + int index = c0 * 256 + c1; 8.49 + if (index == -1) return; 8.50 + i = bucket_B[index]; 8.51 + if (1 < j - i && test != null) 8.52 + x1 = 0; 8.53 + j = i; 8.54 + c1--; 8.55 + } else { 8.56 + c0--; 8.57 + if (j <= 0) 8.58 + break; 8.59 + c1 = 255; 8.60 + } 8.61 + } 8.62 + } 8.63 + 8.64 + public static void main(String args[]) { 8.65 + Test7024475 t = new Test7024475(); 8.66 + bucket_B = new int[256*256]; 8.67 + for (int i = 1; i < 256*256; i++) { 8.68 + bucket_B[i] = 1; 8.69 + } 8.70 + for (int n = 0; n < 100000; n++) { 8.71 + test(t, 2, 85, 1, 134); 8.72 + } 8.73 + } 8.74 +}