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",
|
generate_throw_exception("WrongMethodTypeException throw_exception",
|
||||||
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
||||||
G5_method_type, G3_method_handle);
|
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_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_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_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 =
|
StubRoutines::_handler_for_unsafe_access_entry =
|
||||||
generate_handler_for_unsafe_access();
|
generate_handler_for_unsafe_access();
|
||||||
|
@ -396,7 +396,6 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
|
|||||||
Register Rscratch,
|
Register Rscratch,
|
||||||
Register Rscratch2) {
|
Register Rscratch2) {
|
||||||
const int page_size = os::vm_page_size();
|
const int page_size = os::vm_page_size();
|
||||||
Address saved_exception_pc(G2_thread, JavaThread::saved_exception_pc_offset());
|
|
||||||
Label after_frame_check;
|
Label after_frame_check;
|
||||||
|
|
||||||
assert_different_registers(Rframe_size, Rscratch, Rscratch2);
|
assert_different_registers(Rframe_size, Rscratch, Rscratch2);
|
||||||
@ -436,11 +435,19 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
|
|||||||
// the bottom of the stack
|
// the bottom of the stack
|
||||||
__ cmp_and_brx_short(SP, Rscratch, Assembler::greater, Assembler::pt, after_frame_check);
|
__ 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
|
// 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
|
// if you get to here, then there is enough stack space
|
||||||
__ bind( after_frame_check );
|
__ bind( after_frame_check );
|
||||||
|
@ -2323,6 +2323,9 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
generate_throw_exception("WrongMethodTypeException throw_exception",
|
generate_throw_exception("WrongMethodTypeException throw_exception",
|
||||||
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
||||||
rax, rcx);
|
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_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_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_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
|
// entry points that are platform specific
|
||||||
|
@ -3072,6 +3072,13 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
generate_throw_exception("WrongMethodTypeException throw_exception",
|
generate_throw_exception("WrongMethodTypeException throw_exception",
|
||||||
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
|
||||||
rax, rcx);
|
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() {
|
void generate_all() {
|
||||||
@ -3098,12 +3105,6 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
SharedRuntime::
|
SharedRuntime::
|
||||||
throw_NullPointerException_at_call));
|
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
|
// entry points that are platform specific
|
||||||
StubRoutines::x86::_f2i_fixup = generate_f2i_fixup();
|
StubRoutines::x86::_f2i_fixup = generate_f2i_fixup();
|
||||||
StubRoutines::x86::_f2l_fixup = generate_f2l_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(rsi); // get saved bcp / (c++ prev state ).
|
||||||
|
|
||||||
__ pop(rax); // get return address
|
// Restore sender's sp as SP. This is necessary if the sender's
|
||||||
__ jump(ExternalAddress(Interpreter::throw_StackOverflowError_entry()));
|
// 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
|
// all done with frame size check
|
||||||
__ bind(after_frame_check_pop);
|
__ bind(after_frame_check_pop);
|
||||||
__ pop(rsi);
|
__ pop(rsi);
|
||||||
|
@ -467,8 +467,18 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
|
|||||||
__ cmpptr(rsp, rax);
|
__ cmpptr(rsp, rax);
|
||||||
__ jcc(Assembler::above, after_frame_check);
|
__ jcc(Assembler::above, after_frame_check);
|
||||||
|
|
||||||
__ pop(rax); // get return address
|
// Restore sender's sp as SP. This is necessary if the sender's
|
||||||
__ jump(ExternalAddress(Interpreter::throw_StackOverflowError_entry()));
|
// 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
|
// all done with frame size check
|
||||||
__ bind(after_frame_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