From 61e072d11c8e0cb5879bb733ed1fdd2144326bfd Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Wed, 27 Jul 2022 10:43:52 +0000 Subject: [PATCH] 8290705: StringConcat::validate_mem_flow asserts with "unexpected user: StoreI" Reviewed-by: kvn, xliu --- src/hotspot/share/opto/stringopts.cpp | 15 +++++ .../SideEffectBeforeConstructor.jasm | 58 +++++++++++++++++++ .../TestSideEffectBeforeConstructor.java | 49 ++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/stringopts/SideEffectBeforeConstructor.jasm create mode 100644 test/hotspot/jtreg/compiler/stringopts/TestSideEffectBeforeConstructor.java diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp index 3cda2dfa788..8a533572a51 100644 --- a/src/hotspot/share/opto/stringopts.cpp +++ b/src/hotspot/share/opto/stringopts.cpp @@ -1022,6 +1022,21 @@ bool StringConcat::validate_control_flow() { fail = true; break; } else if (ptr->is_Proj() && ptr->in(0)->is_Initialize()) { + // Check for side effect between Initialize and the constructor + for (SimpleDUIterator iter(ptr); iter.has_next(); iter.next()) { + Node* use = iter.get(); + if (!use->is_CFG() && !use->is_CheckCastPP() && !use->is_Load()) { +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print_cr("unexpected control use of Initialize"); + ptr->in(0)->dump(); // Initialize node + use->dump(1); + } +#endif + fail = true; + break; + } + } ptr = ptr->in(0)->in(0); } else if (ptr->is_Region()) { Node* copy = ptr->as_Region()->is_copy(); diff --git a/test/hotspot/jtreg/compiler/stringopts/SideEffectBeforeConstructor.jasm b/test/hotspot/jtreg/compiler/stringopts/SideEffectBeforeConstructor.jasm new file mode 100644 index 00000000000..cbc6d754ba2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/stringopts/SideEffectBeforeConstructor.jasm @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. 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. + */ + +super public class compiler/stringopts/SideEffectBeforeConstructor + version 51:0 +{ + public static Field result:I; + + static Method "":"()V" + stack 2 locals 0 + { + iconst_0; + putstatic Field result:"I"; + return; + } + public Method "":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + + public static Method test:"(Ljava/lang/String;)V" + stack 4 locals 1 + { + new class java/lang/StringBuffer; + dup; + getstatic Field result:"I"; + iconst_1; + iadd; + putstatic Field result:"I"; + aload_0; + invokespecial Method java/lang/StringBuffer."":"(Ljava/lang/String;)V"; + invokevirtual Method java/lang/StringBuffer.toString:"()Ljava/lang/String;"; + return; + } +} diff --git a/test/hotspot/jtreg/compiler/stringopts/TestSideEffectBeforeConstructor.java b/test/hotspot/jtreg/compiler/stringopts/TestSideEffectBeforeConstructor.java new file mode 100644 index 00000000000..86c5eca1d05 --- /dev/null +++ b/test/hotspot/jtreg/compiler/stringopts/TestSideEffectBeforeConstructor.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. 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 8290705 + * @summary Test correctness of the string concatenation optimization with + * a store between StringBuffer allocation and constructor invocation. + * @compile SideEffectBeforeConstructor.jasm + * @run main/othervm -Xbatch compiler.stringopts.TestSideEffectBeforeConstructor + */ + +package compiler.stringopts; + +public class TestSideEffectBeforeConstructor { + + public static void main(String[] args) { + for (int i = 0; i < 100_000; ++i) { + try { + SideEffectBeforeConstructor.test(null); + } catch (NullPointerException npe) { + // Expected + } + } + if (SideEffectBeforeConstructor.result != 100_000) { + throw new RuntimeException("Unexpected result: " + SideEffectBeforeConstructor.result); + } + } +}