Fri, 24 Jul 2020 13:37:11 +0100
Merge
1.1 --- a/src/share/vm/opto/callnode.cpp Fri Jul 24 13:16:58 2020 +0100 1.2 +++ b/src/share/vm/opto/callnode.cpp Fri Jul 24 13:37:11 2020 +0100 1.3 @@ -1180,6 +1180,14 @@ 1.4 return (TypeFunc::Parms == idx); 1.5 } 1.6 1.7 +void SafePointNode::disconnect_from_root(PhaseIterGVN *igvn) { 1.8 + assert(Opcode() == Op_SafePoint, "only value for safepoint in loops"); 1.9 + int nb = igvn->C->root()->find_prec_edge(this); 1.10 + if (nb != -1) { 1.11 + igvn->C->root()->rm_prec(nb); 1.12 + } 1.13 +} 1.14 + 1.15 //============== SafePointScalarObjectNode ============== 1.16 1.17 SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp,
2.1 --- a/src/share/vm/opto/callnode.hpp Fri Jul 24 13:16:58 2020 +0100 2.2 +++ b/src/share/vm/opto/callnode.hpp Fri Jul 24 13:37:11 2020 +0100 2.3 @@ -459,6 +459,8 @@ 2.4 return !_replaced_nodes.is_empty(); 2.5 } 2.6 2.7 + void disconnect_from_root(PhaseIterGVN *igvn); 2.8 + 2.9 // Standard Node stuff 2.10 virtual int Opcode() const; 2.11 virtual bool pinned() const { return true; }
3.1 --- a/src/share/vm/opto/compile.cpp Fri Jul 24 13:16:58 2020 +0100 3.2 +++ b/src/share/vm/opto/compile.cpp Fri Jul 24 13:37:11 2020 +0100 3.3 @@ -2075,6 +2075,23 @@ 3.4 } 3.5 3.6 3.7 +// Remove edges from "root" to each SafePoint at a backward branch. 3.8 +// They were inserted during parsing (see add_safepoint()) to make 3.9 +// infinite loops without calls or exceptions visible to root, i.e., 3.10 +// useful. 3.11 +void Compile::remove_root_to_sfpts_edges() { 3.12 + Node *r = root(); 3.13 + if (r != NULL) { 3.14 + for (uint i = r->req(); i < r->len(); ++i) { 3.15 + Node *n = r->in(i); 3.16 + if (n != NULL && n->is_SafePoint()) { 3.17 + r->rm_prec(i); 3.18 + --i; 3.19 + } 3.20 + } 3.21 + } 3.22 +} 3.23 + 3.24 //------------------------------Optimize--------------------------------------- 3.25 // Given a graph, optimize it. 3.26 void Compile::Optimize() { 3.27 @@ -2130,6 +2147,10 @@ 3.28 if (failing()) return; 3.29 } 3.30 3.31 + // Now that all inlining is over, cut edge from root to loop 3.32 + // safepoints 3.33 + remove_root_to_sfpts_edges(); 3.34 + 3.35 // Remove the speculative part of types and clean up the graph from 3.36 // the extra CastPP nodes whose only purpose is to carry them. Do 3.37 // that early so that optimizations are not disrupted by the extra 3.38 @@ -3012,8 +3033,10 @@ 3.39 break; 3.40 } 3.41 } 3.42 - assert(proj != NULL, "must be found"); 3.43 - p->subsume_by(proj, this); 3.44 + assert(proj != NULL || p->_con == TypeFunc::I_O, "io may be dropped at an infinite loop"); 3.45 + if (proj != NULL) { 3.46 + p->subsume_by(proj, this); 3.47 + } 3.48 } 3.49 } 3.50 break;
4.1 --- a/src/share/vm/opto/compile.hpp Fri Jul 24 13:16:58 2020 +0100 4.2 +++ b/src/share/vm/opto/compile.hpp Fri Jul 24 13:37:11 2020 +0100 4.3 @@ -959,6 +959,7 @@ 4.4 void inline_incrementally(PhaseIterGVN& igvn); 4.5 void inline_string_calls(bool parse_time); 4.6 void inline_boxing_calls(PhaseIterGVN& igvn); 4.7 + void remove_root_to_sfpts_edges(); 4.8 4.9 // Matching, CFG layout, allocation, code generation 4.10 PhaseCFG* cfg() { return _cfg; }
5.1 --- a/src/share/vm/opto/node.cpp Fri Jul 24 13:16:58 2020 +0100 5.2 +++ b/src/share/vm/opto/node.cpp Fri Jul 24 13:37:11 2020 +0100 5.3 @@ -1329,6 +1329,9 @@ 5.4 5.5 while (nstack.size() > 0) { 5.6 dead = nstack.pop(); 5.7 + if (dead->Opcode() == Op_SafePoint) { 5.8 + dead->as_SafePoint()->disconnect_from_root(igvn); 5.9 + } 5.10 if (dead->outcnt() > 0) { 5.11 // Keep dead node on stack until all uses are processed. 5.12 nstack.push(dead);
6.1 --- a/src/share/vm/opto/phaseX.cpp Fri Jul 24 13:16:58 2020 +0100 6.2 +++ b/src/share/vm/opto/phaseX.cpp Fri Jul 24 13:37:11 2020 +0100 6.3 @@ -419,20 +419,6 @@ 6.4 6.5 // Disconnect 'useless' nodes that are adjacent to useful nodes 6.6 C->remove_useless_nodes(_useful); 6.7 - 6.8 - // Remove edges from "root" to each SafePoint at a backward branch. 6.9 - // They were inserted during parsing (see add_safepoint()) to make infinite 6.10 - // loops without calls or exceptions visible to root, i.e., useful. 6.11 - Node *root = C->root(); 6.12 - if( root != NULL ) { 6.13 - for( uint i = root->req(); i < root->len(); ++i ) { 6.14 - Node *n = root->in(i); 6.15 - if( n != NULL && n->is_SafePoint() ) { 6.16 - root->rm_prec(i); 6.17 - --i; 6.18 - } 6.19 - } 6.20 - } 6.21 } 6.22 6.23 //============================================================================= 6.24 @@ -1258,6 +1244,9 @@ 6.25 6.26 while (_stack.is_nonempty()) { 6.27 dead = _stack.node(); 6.28 + if (dead->Opcode() == Op_SafePoint) { 6.29 + dead->as_SafePoint()->disconnect_from_root(this); 6.30 + } 6.31 uint progress_state = _stack.index(); 6.32 assert(dead != C->root(), "killing root, eh?"); 6.33 assert(!dead->is_top(), "add check for top when pushing"); 6.34 @@ -1352,6 +1341,9 @@ 6.35 //------------------------------subsume_node----------------------------------- 6.36 // Remove users from node 'old' and add them to node 'nn'. 6.37 void PhaseIterGVN::subsume_node( Node *old, Node *nn ) { 6.38 + if (old->Opcode() == Op_SafePoint) { 6.39 + old->as_SafePoint()->disconnect_from_root(this); 6.40 + } 6.41 assert( old != hash_find(old), "should already been removed" ); 6.42 assert( old != C->top(), "cannot subsume top node"); 6.43 // Copy debug or profile information to the new version:
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/compiler/inlining/StringConcatInfiniteLoop.java Fri Jul 24 13:37:11 2020 +0100 7.3 @@ -0,0 +1,54 @@ 7.4 +/* 7.5 + * Copyright (c) 2018, Red Hat, Inc. All rights reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. 7.11 + * 7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.15 + * version 2 for more details (a copy is included in the LICENSE file that 7.16 + * accompanied this code). 7.17 + * 7.18 + * You should have received a copy of the GNU General Public License version 7.19 + * 2 along with this work; if not, write to the Free Software Foundation, 7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.21 + * 7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 7.23 + * or visit www.oracle.com if you need additional information or have any 7.24 + * questions. 7.25 + */ 7.26 + 7.27 +/* 7.28 + * @test 8214862 7.29 + * @summary Multiple passes of PhaseRemoveUseless causes infinite loop to be optimized out 7.30 + * 7.31 + * @run main/othervm -XX:-TieredCompilation -Xcomp -XX:CompileOnly=StringConcatInfiniteLoop::test -XX:CompileCommand=dontinline,*StringBuilder::* StringConcatInfiniteLoop 7.32 + * 7.33 + */ 7.34 + 7.35 +public class StringConcatInfiniteLoop { 7.36 + public static void main(String[] args) { 7.37 + StringBuilder sb = new StringBuilder(); 7.38 + test(sb, "foo", "bar", true); 7.39 + } 7.40 + 7.41 + private static void test(Object v, String s1, String s2, boolean flag) { 7.42 + if (flag) { 7.43 + return; 7.44 + } 7.45 + int i = 0; 7.46 + for (; i < 10; i++); 7.47 + if (i == 10) { 7.48 + v = null; 7.49 + } 7.50 + StringBuilder sb = new StringBuilder(s1); 7.51 + sb.append(s2); 7.52 + while (v == null); 7.53 + } 7.54 + 7.55 + private static class A { 7.56 + } 7.57 +}