diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 87bd928ae407bb26a48d749e93bf3e55d2a6a4d3..115952ad65ce285ac7dd35a89344c4a07e0a500e 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -2990,7 +2990,7 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc, set_control( _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Control) ) ); // create memory projection for i_o set_memory ( _gvn.transform( new (C) ProjNode(allocx, TypeFunc::Memory, true) ), rawidx ); - make_slow_call_ex(allocx, env()->OutOfMemoryError_klass(), true); + make_slow_call_ex(allocx, env()->Throwable_klass(), true); // create a memory projection as for the normal control path Node* malloc = _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Memory)); diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 0f92b53f135ebd44a05cb779948444d0811bc5ec..ac6f4ec8f7662af4c6f4f0d874942858d928f57d 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -509,6 +509,7 @@ void Parse::do_multianewarray() { makecon(TypeKlassPtr::make(array_klass)), dims); } + make_slow_call_ex(c, env()->Throwable_klass(), false); Node* res = _gvn.transform(new (C) ProjNode(c, TypeFunc::Parms)); diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index fb90705726ea2ab32b3170242ba828fe8c000562..7edb97e0bbaba8055de57cf124181db76d76263c 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -989,7 +989,7 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t // since we're notifying the VM on every catch. // Force deoptimization and the rest of the lookup // will be fine. - deoptimize_caller_frame(thread, true); + deoptimize_caller_frame(thread); } // Check the stack guard pages. If enabled, look for handler in this frame; @@ -1143,19 +1143,24 @@ const TypeFunc *OptoRuntime::rethrow_Type() { void OptoRuntime::deoptimize_caller_frame(JavaThread *thread, bool doit) { - // Deoptimize frame - if (doit) { - // Called from within the owner thread, so no need for safepoint - RegisterMap reg_map(thread); - frame stub_frame = thread->last_frame(); - assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check"); - frame caller_frame = stub_frame.sender(®_map); - - // Deoptimize the caller frame. - Deoptimization::deoptimize_frame(thread, caller_frame.id()); + // Deoptimize the caller before continuing, as the compiled + // exception handler table may not be valid. + if (!StressCompiledExceptionHandlers && doit) { + deoptimize_caller_frame(thread); } } +void OptoRuntime::deoptimize_caller_frame(JavaThread *thread) { + // Called from within the owner thread, so no need for safepoint + RegisterMap reg_map(thread); + frame stub_frame = thread->last_frame(); + assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check"); + frame caller_frame = stub_frame.sender(®_map); + + // Deoptimize the caller frame. + Deoptimization::deoptimize_frame(thread, caller_frame.id()); +} + bool OptoRuntime::is_deoptimized_caller_frame(JavaThread *thread) { // Called from within the owner thread, so no need for safepoint diff --git a/hotspot/src/share/vm/opto/runtime.hpp b/hotspot/src/share/vm/opto/runtime.hpp index 13da255b74299f696b20a2aca3bf050a85f1952a..295b71237577376ef7d1517af6ff6b843d143e80 100644 --- a/hotspot/src/share/vm/opto/runtime.hpp +++ b/hotspot/src/share/vm/opto/runtime.hpp @@ -174,6 +174,7 @@ private: static address handle_exception_C (JavaThread* thread); static address handle_exception_C_helper(JavaThread* thread, nmethod*& nm); static address rethrow_C (oopDesc* exception, JavaThread *thread, address return_pc ); + static void deoptimize_caller_frame (JavaThread *thread); static void deoptimize_caller_frame (JavaThread *thread, bool doit); static bool is_deoptimized_caller_frame (JavaThread *thread); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 7743835dcacf73da11d234b215815350a041f943..dd3750cafb6e22233da4471fc67a22ed07d01772 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -922,6 +922,9 @@ class CommandLineFlags { develop(bool, PrintExceptionHandlers, false, \ "Print exception handler tables for all nmethods when generated") \ \ + develop(bool, StressCompiledExceptionHandlers, false, \ + "Exercise compiled exception handlers") \ + \ develop(bool, InterceptOSException, false, \ "Starts debugger when an implicit OS (e.g., NULL) " \ "exception happens") \ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 9ca52bec2cf389c1dbfa0181641b6a74b724f7b2..f9cfe5e9e5d0ad2f117aef94769a537dc11aa13a 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -2190,7 +2190,7 @@ void JavaThread::send_thread_stop(oop java_throwable) { // BiasedLocking needs an updated RegisterMap for the revoke monitors pass RegisterMap reg_map(this, UseBiasedLocking); frame compiled_frame = f.sender(®_map); - if (compiled_frame.can_be_deoptimized()) { + if (!StressCompiledExceptionHandlers && compiled_frame.can_be_deoptimized()) { Deoptimization::deoptimize(this, compiled_frame, ®_map); } } diff --git a/hotspot/test/compiler/8004741/Test8004741.java b/hotspot/test/compiler/8004741/Test8004741.java new file mode 100644 index 0000000000000000000000000000000000000000..95e63b9c0c1c1bba875fdfaba67e7cda61b75e65 --- /dev/null +++ b/hotspot/test/compiler/8004741/Test8004741.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2012, 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 Test8004741.java + * @bug 8004741 + * @summary Missing compiled exception handle table entry for multidimensional array allocation + * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers Test8004741 + * + */ + +import java.util.*; + +public class Test8004741 extends Thread { + + static int[][] test(int a, int b) throws Exception { + int[][] ar = null; + try { + ar = new int[a][b]; + } catch (Error e) { + System.out.println("test got Error"); + passed = true; + throw(e); + } catch (Exception e) { + System.out.println("test got Exception"); + throw(e); + } + return ar; + } + + static boolean passed = false; + + public void run() { + System.out.println("test started"); + try { + while(true) { + test(2,20000); + } + } catch (ThreadDeath e) { + System.out.println("test got ThreadDeath"); + passed = true; + } catch (Error e) { + e.printStackTrace(); + System.out.println("test got Error"); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("test got Exception"); + } + } + + public static void main(String[] args) throws Exception { + for (int n = 0; n < 11000; n++) { + test(2, 20); + } + + // First test exception catch + Test8004741 t = new Test8004741(); + + passed = false; + t.start(); + Thread.sleep(1000); + t.stop(); + + Thread.sleep(5000); + t.join(); + if (passed) { + System.out.println("PASSED"); + } else { + System.out.println("FAILED"); + System.exit(97); + } + } + +};