From d896abb197141d26892cb964da8282ef215192e8 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 29 Apr 2022 08:44:16 +0000 Subject: [PATCH] 8281811: assert(_base == Tuple) failed: Not a Tuple after JDK-8280799 Reviewed-by: mdoerr Backport-of: fcce24c5b3cd1dab755fd9b6779af71f4dd78773 --- src/hotspot/share/opto/loopnode.cpp | 28 ++++---- src/hotspot/share/opto/loopnode.hpp | 14 ++-- .../compiler/TestBarrierAboveProj.java | 71 +++++++++++++++++++ 3 files changed, 96 insertions(+), 17 deletions(-) create mode 100644 test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index b3e7bfe80a0..570f5ab000c 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -2847,12 +2847,12 @@ bool PhaseIdealLoop::only_has_infinite_loops() { //----------------------------build_and_optimize------------------------------- // Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to // its corresponding LoopNode. If 'optimize' is true, do some loop cleanups. -void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { - bool do_split_ifs = (mode == LoopOptsDefault || mode == LoopOptsLastRound); - bool skip_loop_opts = (mode == LoopOptsNone); +void PhaseIdealLoop::build_and_optimize() { + bool do_split_ifs = (_mode == LoopOptsDefault || _mode == LoopOptsLastRound); + bool skip_loop_opts = (_mode == LoopOptsNone); #if INCLUDE_SHENANDOAHGC - bool shenandoah_opts = (mode == LoopOptsShenandoahExpand || - mode == LoopOptsShenandoahPostExpand); + bool shenandoah_opts = (_mode == LoopOptsShenandoahExpand || + _mode == LoopOptsShenandoahPostExpand); #endif ResourceMark rm; @@ -3020,7 +3020,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { // restore major progress flag for (int i = 0; i < old_progress; i++) C->set_major_progress(); - assert(C->unique() == unique, "verification mode made Nodes? ? ?"); + assert(C->unique() == unique, "verification _mode made Nodes? ? ?"); assert(_igvn._worklist.size() == orig_worklist_size, "shouldn't push anything"); return; } @@ -3051,8 +3051,8 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { #ifndef PRODUCT C->verify_graph_edges(); if (_verify_me) { // Nested verify pass? - // Check to see if the verify mode is broken - assert(C->unique() == unique, "non-optimize mode made Nodes? ? ?"); + // Check to see if the verify _mode is broken + assert(C->unique() == unique, "non-optimize _mode made Nodes? ? ?"); return; } if (VerifyLoopOptimizations) verify(); @@ -3077,7 +3077,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { } #if INCLUDE_SHENANDOAHGC - if (UseShenandoahGC && ((ShenandoahBarrierSetC2*) BarrierSet::barrier_set()->barrier_set_c2())->optimize_loops(this, mode, visited, nstack, worklist)) { + if (UseShenandoahGC && ((ShenandoahBarrierSetC2*) BarrierSet::barrier_set()->barrier_set_c2())->optimize_loops(this, _mode, visited, nstack, worklist)) { _igvn.optimize(); if (C->log() != NULL) { log_loop_tree(_ltree_root, _ltree_root, C->log()); @@ -3116,9 +3116,9 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { // that require basic-block info (like cloning through Phi's) if( SplitIfBlocks && do_split_ifs ) { visited.Clear(); - split_if_with_blocks( visited, nstack, mode == LoopOptsLastRound ); + split_if_with_blocks( visited, nstack, _mode == LoopOptsLastRound ); NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); ); - if (mode == LoopOptsLastRound) { + if (_mode == LoopOptsLastRound) { C->set_major_progress(); } } @@ -4480,9 +4480,13 @@ void PhaseIdealLoop::build_loop_late_post( Node *n ) { } least = new_ctrl; } +#if INCLUDE_SHENANDOAHGC + bool shenandoah_opts = (_mode == LoopOptsShenandoahExpand || + _mode == LoopOptsShenandoahPostExpand); +#endif // Try not to place code on a loop entry projection // which can inhibit range check elimination. - if (least != early) { + if (least != early SHENANDOAHGC_ONLY(&& !shenandoah_opts)) { Node* ctrl_out = least->unique_ctrl_out(); if (ctrl_out && ctrl_out->is_Loop() && least == ctrl_out->in(LoopNode::EntryControl) && diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 3f327ea2dbb..06c1237e919 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -927,6 +927,7 @@ class PhaseIdealLoop : public PhaseTransform { Node **_idom; // Array of immediate dominators uint *_dom_depth; // Used for fast LCA test GrowableArray* _dom_stk; // For recomputation of dom depth + LoopOptsMode _mode; public: Node* idom_no_update(Node* d) const { @@ -978,12 +979,13 @@ class PhaseIdealLoop : public PhaseTransform { _dom_lca_tags(arena()), // Thread::resource_area _nodes_required(UINT_MAX), _verify_me(NULL), - _verify_only(true) { - build_and_optimize(LoopOptsVerify); + _verify_only(true), + _mode(LoopOptsVerify) { + build_and_optimize(); } // build the loop tree and perform any requested optimizations - void build_and_optimize(LoopOptsMode mode); + void build_and_optimize(); // Dominators for the sea of nodes void Dominators(); @@ -998,9 +1000,10 @@ class PhaseIdealLoop : public PhaseTransform { _igvn(igvn), _dom_lca_tags(arena()), // Thread::resource_area _nodes_required(UINT_MAX), + _mode(mode), _verify_me(NULL), _verify_only(false) { - build_and_optimize(mode); + build_and_optimize(); } // Verify that verify_me made the same decisions as a fresh run. @@ -1010,8 +1013,9 @@ class PhaseIdealLoop : public PhaseTransform { _dom_lca_tags(arena()), // Thread::resource_area _nodes_required(UINT_MAX), _verify_me(verify_me), + _mode(LoopOptsVerify), _verify_only(false) { - build_and_optimize(LoopOptsVerify); + build_and_optimize(); } // Build and verify the loop tree without modifying the graph. This diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java new file mode 100644 index 00000000000..560b6f34617 --- /dev/null +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, 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 8281811 + * @summary assert(_base == Tuple) failed: Not a Tuple after JDK-8280799 + * @requires vm.gc.Shenandoah + * @run main/othervm -XX:+UseShenandoahGC -XX:-BackgroundCompilation -XX:LoopMaxUnroll=1 TestBarrierAboveProj + */ + + +public class TestBarrierAboveProj { + private static C objField = new C(); + private static final Object[] arrayField = new Object[1000]; + private static volatile int volatileField; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test1(); + test2(); + } + } + + private static float test1() { + float v = 1; + for (int i = 1; i < 1000; i++) { + if (objField == arrayField[i]) { + return v; + } + v *= 2; + } + return v; + } + + private static float test2() { + float v = 1; + volatileField = 0x42; + for (int i = 1; i < 1000; i++) { + if (objField == arrayField[i]) { + return v; + } + v *= 2; + } + return v; + } + + private static class C { + public float floatField; + } +}