7116216: StackOverflow GC crash
GC crash for explicit stack overflow checks after a C2I transition. Co-authored-by: Yang Wang <yang02.wang@sap.com> Reviewed-by: coleenp, never
This commit is contained in:
parent
6e894d5474
commit
82a0e26723
@ -3414,6 +3414,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
generate_throw_exception("WrongMethodTypeException throw_exception",
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
||||
G5_method_type, G3_method_handle);
|
||||
|
||||
// Build this early so it's available for the interpreter.
|
||||
StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
|
||||
}
|
||||
|
||||
|
||||
@ -3427,7 +3430,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError));
|
||||
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
|
||||
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
|
||||
StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
|
||||
|
||||
StubRoutines::_handler_for_unsafe_access_entry =
|
||||
generate_handler_for_unsafe_access();
|
||||
|
@ -396,7 +396,6 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
|
||||
Register Rscratch,
|
||||
Register Rscratch2) {
|
||||
const int page_size = os::vm_page_size();
|
||||
Address saved_exception_pc(G2_thread, JavaThread::saved_exception_pc_offset());
|
||||
Label after_frame_check;
|
||||
|
||||
assert_different_registers(Rframe_size, Rscratch, Rscratch2);
|
||||
@ -436,11 +435,19 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
|
||||
// the bottom of the stack
|
||||
__ cmp_and_brx_short(SP, Rscratch, Assembler::greater, Assembler::pt, after_frame_check);
|
||||
|
||||
// Save the return address as the exception pc
|
||||
__ st_ptr(O7, saved_exception_pc);
|
||||
|
||||
// the stack will overflow, throw an exception
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_StackOverflowError));
|
||||
|
||||
// Note that SP is restored to sender's sp (in the delay slot). This
|
||||
// is necessary if the sender's frame is an extended compiled frame
|
||||
// (see gen_c2i_adapter()) and safer anyway in case of JSR292
|
||||
// adaptations.
|
||||
|
||||
// Note also that the restored frame is not necessarily interpreted.
|
||||
// Use the shared runtime version of the StackOverflowError.
|
||||
assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "stub not yet generated");
|
||||
AddressLiteral stub(StubRoutines::throw_StackOverflowError_entry());
|
||||
__ jump_to(stub, Rscratch);
|
||||
__ delayed()->mov(O5_savedSP, SP);
|
||||
|
||||
// if you get to here, then there is enough stack space
|
||||
__ bind( after_frame_check );
|
||||
|
@ -2323,6 +2323,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
generate_throw_exception("WrongMethodTypeException throw_exception",
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
||||
rax, rcx);
|
||||
|
||||
// Build this early so it's available for the interpreter
|
||||
StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
|
||||
}
|
||||
|
||||
|
||||
@ -2334,7 +2337,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError));
|
||||
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
|
||||
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
|
||||
StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// entry points that are platform specific
|
||||
|
@ -3072,6 +3072,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||
generate_throw_exception("WrongMethodTypeException throw_exception",
|
||||
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
||||
rax, rcx);
|
||||
|
||||
// Build this early so it's available for the interpreter.
|
||||
StubRoutines::_throw_StackOverflowError_entry =
|
||||
generate_throw_exception("StackOverflowError throw_exception",
|
||||
CAST_FROM_FN_PTR(address,
|
||||
SharedRuntime::
|
||||
throw_StackOverflowError));
|
||||
}
|
||||
|
||||
void generate_all() {
|
||||
@ -3098,12 +3105,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
SharedRuntime::
|
||||
throw_NullPointerException_at_call));
|
||||
|
||||
StubRoutines::_throw_StackOverflowError_entry =
|
||||
generate_throw_exception("StackOverflowError throw_exception",
|
||||
CAST_FROM_FN_PTR(address,
|
||||
SharedRuntime::
|
||||
throw_StackOverflowError));
|
||||
|
||||
// entry points that are platform specific
|
||||
StubRoutines::x86::_f2i_fixup = generate_f2i_fixup();
|
||||
StubRoutines::x86::_f2l_fixup = generate_f2l_fixup();
|
||||
|
@ -522,9 +522,18 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
|
||||
|
||||
__ pop(rsi); // get saved bcp / (c++ prev state ).
|
||||
|
||||
__ pop(rax); // get return address
|
||||
__ jump(ExternalAddress(Interpreter::throw_StackOverflowError_entry()));
|
||||
// Restore sender's sp as SP. This is necessary if the sender's
|
||||
// frame is an extended compiled frame (see gen_c2i_adapter())
|
||||
// and safer anyway in case of JSR292 adaptations.
|
||||
|
||||
__ pop(rax); // return address must be moved if SP is changed
|
||||
__ mov(rsp, rsi);
|
||||
__ push(rax);
|
||||
|
||||
// Note: the restored frame is not necessarily interpreted.
|
||||
// Use the shared runtime version of the StackOverflowError.
|
||||
assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "stub not yet generated");
|
||||
__ jump(ExternalAddress(StubRoutines::throw_StackOverflowError_entry()));
|
||||
// all done with frame size check
|
||||
__ bind(after_frame_check_pop);
|
||||
__ pop(rsi);
|
||||
|
@ -467,8 +467,18 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
|
||||
__ cmpptr(rsp, rax);
|
||||
__ jcc(Assembler::above, after_frame_check);
|
||||
|
||||
__ pop(rax); // get return address
|
||||
__ jump(ExternalAddress(Interpreter::throw_StackOverflowError_entry()));
|
||||
// Restore sender's sp as SP. This is necessary if the sender's
|
||||
// frame is an extended compiled frame (see gen_c2i_adapter())
|
||||
// and safer anyway in case of JSR292 adaptations.
|
||||
|
||||
__ pop(rax); // return address must be moved if SP is changed
|
||||
__ mov(rsp, r13);
|
||||
__ push(rax);
|
||||
|
||||
// Note: the restored frame is not necessarily interpreted.
|
||||
// Use the shared runtime version of the StackOverflowError.
|
||||
assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "stub not yet generated");
|
||||
__ jump(ExternalAddress(StubRoutines::throw_StackOverflowError_entry()));
|
||||
|
||||
// all done with frame size check
|
||||
__ bind(after_frame_check);
|
||||
|
1329
hotspot/test/compiler/7116216/LargeFrame.java
Normal file
1329
hotspot/test/compiler/7116216/LargeFrame.java
Normal file
File diff suppressed because it is too large
Load Diff
64
hotspot/test/compiler/7116216/StackOverflow.java
Normal file
64
hotspot/test/compiler/7116216/StackOverflow.java
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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 7116216
|
||||
* @summary The vm crashes when GC happens during throwing a StackOverflow exception
|
||||
*
|
||||
* @run main/othervm -Xcomp -Xbatch StackOverflow
|
||||
*/
|
||||
|
||||
class StackOverflow {
|
||||
static String stackOverflow_largeFrame_liveOopForGC;
|
||||
|
||||
public static int stackOverflow_largeFrame(int call_count, String liveOopForGC) {
|
||||
try {
|
||||
int return_count = stackOverflow_largeFrame(++call_count, liveOopForGC);
|
||||
if (return_count == 0) {
|
||||
try {
|
||||
LargeFrame.method_with_many_locals(liveOopForGC, 2,3,4,5,6,7,liveOopForGC);
|
||||
} catch (StackOverflowError e2) {
|
||||
// access liveOopForGC to make it a live variable
|
||||
stackOverflow_largeFrame_liveOopForGC = liveOopForGC;
|
||||
}
|
||||
}
|
||||
return return_count - 1;
|
||||
} catch (StackOverflowError e) {
|
||||
// Return a value that is large enough such that no unrecoverable
|
||||
// stack overflow will occur afterwards, but that is small enough
|
||||
// such that calling LargeFrame.method_with_many_locals() will
|
||||
// cause a StackOverflowError.
|
||||
// Don't use a call here because we're out of stack space anyway!
|
||||
int tmp = call_count / 2;
|
||||
return (tmp < 100 ? tmp : 100);
|
||||
}
|
||||
}
|
||||
public static void main(String args[]) {
|
||||
LargeFrame.method_with_many_locals(new Object(), 2,3,4,5,6,7,new Object());
|
||||
|
||||
stackOverflow_largeFrame(0, "this is a live oop to test GC");
|
||||
System.out.println("finished ok!");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user