From 0ece249f52929ad77810929c4257caea0ca4a05c Mon Sep 17 00:00:00 2001 From: rwestrel Date: Fri, 23 Jul 2021 17:34:06 +0200 Subject: [PATCH] fix & test --- .../gc/shenandoah/c2/shenandoahSupport.cpp | 104 +++++++++++------- .../gc/shenandoah/c2/shenandoahSupport.hpp | 2 + src/hotspot/share/opto/cfgnode.cpp | 2 +- .../compiler/c2/TestInfiniteLoopCCP.java | 74 +++++++++++++ 4 files changed, 139 insertions(+), 43 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestInfiniteLoopCCP.java diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 45de2647375c2..5ba3828b2d3d7 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -2170,48 +2170,7 @@ void MemoryGraphFixer::collect_memory_nodes() { assert(call->is_Call(), ""); mem = call->in(TypeFunc::Memory); } else if (in->Opcode() == Op_NeverBranch) { - Node* head = in->in(0); - assert(head->is_Region(), "unexpected infinite loop graph shape"); - - Node* phi_mem = NULL; - for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) { - Node* u = head->fast_out(j); - if (u->is_Phi() && u->bottom_type() == Type::MEMORY) { - if (_phase->C->get_alias_index(u->adr_type()) == _alias) { - assert(phi_mem == NULL || phi_mem->adr_type() == TypePtr::BOTTOM, ""); - phi_mem = u; - } else if (u->adr_type() == TypePtr::BOTTOM) { - assert(phi_mem == NULL || _phase->C->get_alias_index(phi_mem->adr_type()) == _alias, ""); - if (phi_mem == NULL) { - phi_mem = u; - } - } - } - } - if (phi_mem == NULL) { - for (uint j = 1; j < head->req(); j++) { - Node* tail = head->in(j); - if (!_phase->is_dominator(head, tail)) { - continue; - } - Node* c = tail; - while (c != head) { - if (c->is_SafePoint() && !c->is_CallLeaf()) { - Node* m =c->in(TypeFunc::Memory); - if (m->is_MergeMem()) { - m = m->as_MergeMem()->memory_at(_alias); - } - assert(mem == NULL || mem == m, "several memory states"); - mem = m; - } - c = _phase->idom(c); - } - assert(mem != NULL, "should have found safepoint"); - } - assert(mem != NULL, "should have found safepoint"); - } else { - mem = phi_mem; - } + mem = collect_memory_for_infinite_loop(in); } } } else { @@ -2435,6 +2394,67 @@ void MemoryGraphFixer::collect_memory_nodes() { } } +Node* MemoryGraphFixer::collect_memory_for_infinite_loop(const Node* in) { + Node* mem = NULL; + Node* head = in->in(0); + assert(head->is_Region(), "unexpected infinite loop graph shape"); + + Node* phi_mem = NULL; + for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) { + Node* u = head->fast_out(j); + if (u->is_Phi() && u->bottom_type() == Type::MEMORY) { + if (_phase->C->get_alias_index(u->adr_type()) == _alias) { + assert(phi_mem == NULL || phi_mem->adr_type() == TypePtr::BOTTOM, ""); + phi_mem = u; + } else if (u->adr_type() == TypePtr::BOTTOM) { + assert(phi_mem == NULL || _phase->C->get_alias_index(phi_mem->adr_type()) == _alias, ""); + if (phi_mem == NULL) { + phi_mem = u; + } + } + } + } + if (phi_mem == NULL) { + ResourceMark rm; + Node_Stack stack(0); + stack.push(head, 1); + do { + Node* n = stack.node(); + uint i = stack.index(); + if (i >= n->req()) { + stack.pop(); + } else { + stack.set_index(i + 1); + Node* c = n->in(i); + assert(c != head, "should have found a safepoint on the way"); + if (stack.size() != 1 || _phase->is_dominator(head, c)) { + for (;;) { + if (c->is_Region()) { + stack.push(c, 1); + break; + } else if (c->is_SafePoint() && !c->is_CallLeaf()) { + Node* m = c->in(TypeFunc::Memory); + if (m->is_MergeMem()) { + m = m->as_MergeMem()->memory_at(_alias); + } + assert(mem == NULL || mem == m, "several memory states"); + mem = m; + break; + } else { + assert(c != c->in(0), ""); + c = c->in(0); + } + } + } + } + } while (stack.size() > 0); + assert(mem != NULL, "should have found safepoint"); + } else { + mem = phi_mem; + } + return mem; +} + Node* MemoryGraphFixer::get_ctrl(Node* n) const { Node* c = _phase->get_ctrl(n); if (n->is_Proj() && n->in(0) != NULL && n->in(0)->is_Call()) { diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp index 1890c40ad5836..6632e42b36f07 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp @@ -131,6 +131,8 @@ class MemoryGraphFixer : public ResourceObj { Node* find_mem(Node* ctrl, Node* n) const; void fix_mem(Node* ctrl, Node* region, Node* mem, Node* mem_for_ctrl, Node* mem_phi, Unique_Node_List& uses); int alias() const { return _alias; } + + Node* collect_memory_for_infinite_loop(const Node* in); }; class ShenandoahCompareAndSwapPNode : public CompareAndSwapPNode { diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index e44842e3fb6d0..b1b32dee3de19 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2717,7 +2717,7 @@ const Type* NeverBranchNode::Value(PhaseGVN* phase) const { //------------------------------Ideal------------------------------------------ // Check for no longer being part of a loop Node *NeverBranchNode::Ideal(PhaseGVN *phase, bool can_reshape) { - if (can_reshape && !in(0)->is_Loop()) { + if (can_reshape && !in(0)->is_Region()) { // Dead code elimination can sometimes delete this projection so // if it's not there, there's nothing to do. Node* fallthru = proj_out_or_null(0); diff --git a/test/hotspot/jtreg/compiler/c2/TestInfiniteLoopCCP.java b/test/hotspot/jtreg/compiler/c2/TestInfiniteLoopCCP.java new file mode 100644 index 0000000000000..f67125d63a727 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestInfiniteLoopCCP.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8271340 + * @summary Crash PhaseIdealLoop::clone_outer_loop + * + * @run main/othervm TestInfiniteLoopCCP + * + */ + +public class TestInfiniteLoopCCP { + + public boolean m3 (long a_lo0, short a_sh1){ + long loa6[][] = new long[560][1792]; + + loa6[-128][0] = 1345348328L; + + return false; + } + + public void mainTest (String[] args){ + short sh16 = (short)-32; + for (int i17 = 0; i17 < 29; i17++) { + if (i17 == 8) { + i17 = 129; + for (int i18 = 0; i18 < 27; i18++) { + i18 = 16; + } + } + } + + try { + m3(4130511410L, (short)(sh16 % sh16)); + } catch (ArithmeticException a_e) {} + } + + + public static void main(String[] args) throws Exception{ + Thread thread = new Thread() { + public void run() { + TestInfiniteLoopCCP instance = new TestInfiniteLoopCCP(); + for (int i = 0; i < 100; ++i) { + instance.mainTest(args); + } + } + }; + // Give thread some time to trigger compilation + thread.setDaemon(true); + thread.start(); + Thread.sleep(/*Utils.adjustTimeout(4000)*/4000); + } +}