From 388ab684971cedf99c930326b6e579b28455b462 Mon Sep 17 00:00:00 2001 From: duke Date: Thu, 26 Sep 2024 07:59:10 +0000 Subject: [PATCH] Backport caf28d4ac5711cc864a05fbdd64451d364c599ef --- src/hotspot/share/c1/c1_GraphBuilder.cpp | 8 ++++ src/hotspot/share/compiler/methodLiveness.cpp | 8 +++- src/hotspot/share/oops/generateOopMap.cpp | 18 ++++---- .../jtreg/runtime/interpreter/LastJsr.jasm | 35 ++++++++++++++++ .../runtime/interpreter/LastJsrReachable.jasm | 37 ++++++++++++++++ .../runtime/interpreter/LastJsrTest.java | 42 +++++++++++++++++++ 6 files changed, 138 insertions(+), 10 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/interpreter/LastJsr.jasm create mode 100644 test/hotspot/jtreg/runtime/interpreter/LastJsrReachable.jasm create mode 100644 test/hotspot/jtreg/runtime/interpreter/LastJsrTest.java diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index d40d7cfb119..2f7b2d52737 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -1388,6 +1388,11 @@ void GraphBuilder::jsr(int dest) { // If the bytecodes are strange (jumping out of a jsr block) then we // might end up trying to re-parse a block containing a jsr which // has already been activated. Watch for this case and bail out. + if (next_bci() >= method()->code_size()) { + // This can happen if the subroutine does not terminate with a ret, + // effectively turning the jsr into a goto. + BAILOUT("too-complicated jsr/ret structure"); + } for (ScopeData* cur_scope_data = scope_data(); cur_scope_data != nullptr && cur_scope_data->parsing_jsr() && cur_scope_data->scope() == scope(); cur_scope_data = cur_scope_data->parent()) { @@ -3716,6 +3721,9 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee, bool ignore_return) { bool GraphBuilder::try_inline_jsr(int jsr_dest_bci) { // Introduce a new callee continuation point - all Ret instructions // will be replaced with Gotos to this point. + if (next_bci() >= method()->code_size()) { + return false; + } BlockBegin* cont = block_at(next_bci()); assert(cont != nullptr, "continuation must exist (BlockListBuilder starts a new block after a jsr"); diff --git a/src/hotspot/share/compiler/methodLiveness.cpp b/src/hotspot/share/compiler/methodLiveness.cpp index 1b764882d10..7d65b20a159 100644 --- a/src/hotspot/share/compiler/methodLiveness.cpp +++ b/src/hotspot/share/compiler/methodLiveness.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -222,6 +222,9 @@ void MethodLiveness::init_basic_blocks() { dest = _block_map->at(bytes.get_dest()); assert(dest != nullptr, "branch destination must start a block."); dest->add_normal_predecessor(current_block); + if (bci + Bytecodes::length_for(code) >= method_len) { + break; + } BasicBlock *jsrExit = _block_map->at(current_block->limit_bci()); assert(jsrExit != nullptr, "jsr return bci must start a block."); jsr_exit_list->append(jsrExit); @@ -232,6 +235,9 @@ void MethodLiveness::init_basic_blocks() { dest = _block_map->at(bytes.get_far_dest()); assert(dest != nullptr, "branch destination must start a block."); dest->add_normal_predecessor(current_block); + if (bci + Bytecodes::length_for(code) >= method_len) { + break; + } BasicBlock *jsrExit = _block_map->at(current_block->limit_bci()); assert(jsrExit != nullptr, "jsr return bci must start a block."); jsr_exit_list->append(jsrExit); diff --git a/src/hotspot/share/oops/generateOopMap.cpp b/src/hotspot/share/oops/generateOopMap.cpp index eaa30b8d0c1..1f5b663a10d 100644 --- a/src/hotspot/share/oops/generateOopMap.cpp +++ b/src/hotspot/share/oops/generateOopMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -436,12 +436,12 @@ void GenerateOopMap::mark_bbheaders_and_count_gc_points() { /* We will also mark successors of jsr's as basic block headers. */ switch (bytecode) { case Bytecodes::_jsr: - assert(!fellThrough, "should not happen"); - bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), nullptr); - break; case Bytecodes::_jsr_w: assert(!fellThrough, "should not happen"); - bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), nullptr); + // If this is the last bytecode, there is no successor to mark + if (bci + Bytecodes::length_for(bytecode) < method()->code_size()) { + bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), nullptr); + } break; default: break; @@ -502,7 +502,10 @@ void GenerateOopMap::mark_reachable_code() { case Bytecodes::_jsr: case Bytecodes::_jsr_w: assert(!fell_through, "should not happen"); - reachable_basicblock(this, bci + Bytecodes::length_for(bytecode), &change); + // If this is the last bytecode, there is no successor to mark + if (bci + Bytecodes::length_for(bytecode) < method()->code_size()) { + reachable_basicblock(this, bci + Bytecodes::length_for(bytecode), &change); + } break; default: break; @@ -586,9 +589,6 @@ bool GenerateOopMap::jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, int * case Bytecodes::_jsr: assert(bcs->is_wide()==false, "sanity check"); (*jmpFct)(this, bcs->dest(), data); - - - break; case Bytecodes::_jsr_w: (*jmpFct)(this, bcs->dest_w(), data); diff --git a/test/hotspot/jtreg/runtime/interpreter/LastJsr.jasm b/test/hotspot/jtreg/runtime/interpreter/LastJsr.jasm new file mode 100644 index 00000000000..4f53cbc18ad --- /dev/null +++ b/test/hotspot/jtreg/runtime/interpreter/LastJsr.jasm @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024, 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 LastJsr +{ + public static Method test:"()V" + stack 100 locals 100 + { + return; + LABEL: + nop; + jsr LABEL; // bci=2. Compute bci + length(jsr) -> bci = 5 accessed, out of bounds. + } +} diff --git a/test/hotspot/jtreg/runtime/interpreter/LastJsrReachable.jasm b/test/hotspot/jtreg/runtime/interpreter/LastJsrReachable.jasm new file mode 100644 index 00000000000..5bcc3ffd382 --- /dev/null +++ b/test/hotspot/jtreg/runtime/interpreter/LastJsrReachable.jasm @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024, 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 LastJsrReachable +{ + public static Method test:"()V" + stack 100 locals 100 + { + goto LB2; + LABEL: + return; + LB2: + nop; + jsr LABEL; + } +} diff --git a/test/hotspot/jtreg/runtime/interpreter/LastJsrTest.java b/test/hotspot/jtreg/runtime/interpreter/LastJsrTest.java new file mode 100644 index 00000000000..fd9cffe002d --- /dev/null +++ b/test/hotspot/jtreg/runtime/interpreter/LastJsrTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024, 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 8335664 8338924 + * @summary Ensure a program that ends with a JSR does not crash + * @library /test/lib + * @compile LastJsr.jasm + * @compile LastJsrReachable.jasm + * @run main/othervm -Xbatch LastJsrTest + */ + +public class LastJsrTest { + public static void main(String[] args) { + for (int i = 0; i < 1000; ++i) { + LastJsr.test(); + LastJsrReachable.test(); + } + System.out.println("PASSED"); + } +}