From 35a7eff951e2f5cd2e9da0239412c6210d8b52ad Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 15 May 2020 10:24:38 +0200 Subject: [PATCH] 8244721: CTW: C2 (Shenandoah) compilation fails with "unexpected infinite loop graph shape" Reviewed-by: shade --- .../gc/shenandoah/c2/shenandoahSupport.cpp | 37 +++++++++++------- .../compiler/BarrierInInfiniteLoop.java | 38 +++++++++++++++++-- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index aac3d39a1fc..cdd900e02e5 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -2101,17 +2101,7 @@ void MemoryGraphFixer::collect_memory_nodes() { mem = call->in(TypeFunc::Memory); } else if (in->Opcode() == Op_NeverBranch) { Node* head = in->in(0); - assert(head->is_Region() && head->req() == 3, "unexpected infinite loop graph shape"); - assert(_phase->is_dominator(head, head->in(1)) || _phase->is_dominator(head, head->in(2)), "no back branch?"); - Node* tail = _phase->is_dominator(head, head->in(1)) ? head->in(1) : head->in(2); - Node* c = tail; - while (c != head) { - if (c->is_SafePoint() && !c->is_CallLeaf()) { - mem = c->in(TypeFunc::Memory); - } - c = _phase->idom(c); - } - assert(mem != NULL, "should have found safepoint"); + 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++) { @@ -2128,7 +2118,28 @@ void MemoryGraphFixer::collect_memory_nodes() { } } } - if (phi_mem != NULL) { + 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; } } @@ -2237,7 +2248,7 @@ void MemoryGraphFixer::collect_memory_nodes() { assert(m != NULL || (c->is_Loop() && j == LoopNode::LoopBackControl && iteration == 1) || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "expect memory state"); if (m != NULL) { if (m == prev_region && ((c->is_Loop() && j == LoopNode::LoopBackControl) || (prev_region->is_Phi() && prev_region->in(0) == c))) { - assert(c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop(), ""); + assert(c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), ""); // continue } else if (unique == NULL) { unique = m; diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/BarrierInInfiniteLoop.java b/test/hotspot/jtreg/gc/shenandoah/compiler/BarrierInInfiniteLoop.java index f391cfb5628..edf5c0036da 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/BarrierInInfiniteLoop.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/BarrierInInfiniteLoop.java @@ -23,29 +23,59 @@ /** * @test - * @bug 8237837 + * @bug 8237837 8244721 * @summary Shenandoah: assert(mem == __null) failed: only one safepoint * @key gc * @requires vm.flavor == "server" * @requires vm.gc.Shenandoah & !vm.graal.enabled * - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xcomp -XX:CompileOnly=BarrierInInfiniteLoop::test -XX:CompileCommand=quiet BarrierInInfiniteLoop + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xcomp -XX:CompileOnly=BarrierInInfiniteLoop::test1 + * -XX:CompileOnly=BarrierInInfiniteLoop::test2 -XX:CompileOnly=BarrierInInfiniteLoop::test3 -XX:CompileCommand=quiet BarrierInInfiniteLoop * */ public class BarrierInInfiniteLoop { private static Object field1 = new Object(); private static Object field2 = new Object(); + private static int field3; public static void main(String[] args) { - test(false); + test1(false); + test2(false, false); + test3(false); } - private static void test(boolean flag) { + private static void test1(boolean flag) { if (flag) { for (;;) { field1 = field2; } } } + + private static void test2(boolean flag1, boolean flag2) { + if (flag1) { + for (;;) { + for (;;) { + if (flag2) { + break; + } + field1 = field2; + } + } + } + } + + private static void test3(boolean flag) { + if (flag) { + for (;;) { + for (;;) { + field3 = 42; + if (field1 == field2) { + break; + } + } + } + } + } }