8209825: guarantee(false) failed: wrong number of expression stack elements during deopt

Reviewed-by: kvn, thartmann
This commit is contained in:
Dean Long 2018-08-24 11:56:14 -07:00
parent 423c207dc7
commit 347b95d500
2 changed files with 34 additions and 29 deletions

View file

@ -703,13 +703,12 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
// a given bytecode or the state after, so we try both // a given bytecode or the state after, so we try both
if (!Bytecodes::is_invoke(cur_code) && cur_code != Bytecodes::_athrow) { if (!Bytecodes::is_invoke(cur_code) && cur_code != Bytecodes::_athrow) {
// Get expression stack size for the next bytecode // Get expression stack size for the next bytecode
InterpreterOopMap next_mask;
OopMapCache::compute_one_oop_map(mh, str.bci(), &next_mask);
next_mask_expression_stack_size = next_mask.expression_stack_size();
if (Bytecodes::is_invoke(next_code)) { if (Bytecodes::is_invoke(next_code)) {
Bytecode_invoke invoke(mh, str.bci()); Bytecode_invoke invoke(mh, str.bci());
next_mask_expression_stack_size = invoke.size_of_parameters(); next_mask_expression_stack_size += invoke.size_of_parameters();
} else {
InterpreterOopMap next_mask;
OopMapCache::compute_one_oop_map(mh, str.bci(), &next_mask);
next_mask_expression_stack_size = next_mask.expression_stack_size();
} }
// Need to subtract off the size of the result type of // Need to subtract off the size of the result type of
// the bytecode because this is not described in the // the bytecode because this is not described in the
@ -739,28 +738,30 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
(is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute || el->should_reexecute()) && (is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute || el->should_reexecute()) &&
(iframe->interpreter_frame_expression_stack_size() == mask.expression_stack_size() + cur_invoke_parameter_size)) (iframe->interpreter_frame_expression_stack_size() == mask.expression_stack_size() + cur_invoke_parameter_size))
)) { )) {
ttyLocker ttyl; {
ttyLocker ttyl;
// Print out some information that will help us debug the problem // Print out some information that will help us debug the problem
tty->print_cr("Wrong number of expression stack elements during deoptimization"); tty->print_cr("Wrong number of expression stack elements during deoptimization");
tty->print_cr(" Error occurred while verifying frame %d (0..%d, 0 is topmost)", i, cur_array->frames() - 1); tty->print_cr(" Error occurred while verifying frame %d (0..%d, 0 is topmost)", i, cur_array->frames() - 1);
tty->print_cr(" Fabricated interpreter frame had %d expression stack elements", tty->print_cr(" Fabricated interpreter frame had %d expression stack elements",
iframe->interpreter_frame_expression_stack_size()); iframe->interpreter_frame_expression_stack_size());
tty->print_cr(" Interpreter oop map had %d expression stack elements", mask.expression_stack_size()); tty->print_cr(" Interpreter oop map had %d expression stack elements", mask.expression_stack_size());
tty->print_cr(" try_next_mask = %d", try_next_mask); tty->print_cr(" try_next_mask = %d", try_next_mask);
tty->print_cr(" next_mask_expression_stack_size = %d", next_mask_expression_stack_size); tty->print_cr(" next_mask_expression_stack_size = %d", next_mask_expression_stack_size);
tty->print_cr(" callee_size_of_parameters = %d", callee_size_of_parameters); tty->print_cr(" callee_size_of_parameters = %d", callee_size_of_parameters);
tty->print_cr(" callee_max_locals = %d", callee_max_locals); tty->print_cr(" callee_max_locals = %d", callee_max_locals);
tty->print_cr(" top_frame_expression_stack_adjustment = %d", top_frame_expression_stack_adjustment); tty->print_cr(" top_frame_expression_stack_adjustment = %d", top_frame_expression_stack_adjustment);
tty->print_cr(" exec_mode = %d", exec_mode); tty->print_cr(" exec_mode = %d", exec_mode);
tty->print_cr(" cur_invoke_parameter_size = %d", cur_invoke_parameter_size); tty->print_cr(" cur_invoke_parameter_size = %d", cur_invoke_parameter_size);
tty->print_cr(" Thread = " INTPTR_FORMAT ", thread ID = %d", p2i(thread), thread->osthread()->thread_id()); tty->print_cr(" Thread = " INTPTR_FORMAT ", thread ID = %d", p2i(thread), thread->osthread()->thread_id());
tty->print_cr(" Interpreted frames:"); tty->print_cr(" Interpreted frames:");
for (int k = 0; k < cur_array->frames(); k++) { for (int k = 0; k < cur_array->frames(); k++) {
vframeArrayElement* el = cur_array->element(k); vframeArrayElement* el = cur_array->element(k);
tty->print_cr(" %s (bci %d)", el->method()->name_and_sig_as_C_string(), el->bci()); tty->print_cr(" %s (bci %d)", el->method()->name_and_sig_as_C_string(), el->bci());
} }
cur_array->print_on_2(tty); cur_array->print_on_2(tty);
} // release tty lock before calling guarantee
guarantee(false, "wrong number of expression stack elements during deopt"); guarantee(false, "wrong number of expression stack elements during deopt");
} }
VerifyOopClosure verify; VerifyOopClosure verify;

View file

@ -25,8 +25,10 @@
/* /*
* @test TestVerifyStackAfterDeopt * @test TestVerifyStackAfterDeopt
* @bug 8148871 * @bug 8148871
* @bug 8209825
* @summary Checks VerifyStack after deoptimization of array allocation slow call * @summary Checks VerifyStack after deoptimization of array allocation slow call
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TieredStopAtLevel=1 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TieredStopAtLevel=1
* -XX:MinTLABSize=1k -XX:TLABSize=1k
* -XX:+DeoptimizeALot -XX:+VerifyStack * -XX:+DeoptimizeALot -XX:+VerifyStack
* compiler.interpreter.TestVerifyStackAfterDeopt * compiler.interpreter.TestVerifyStackAfterDeopt
*/ */
@ -35,17 +37,19 @@ package compiler.interpreter;
public class TestVerifyStackAfterDeopt { public class TestVerifyStackAfterDeopt {
private void method(Object[] a) { private long method(long l1, long l2, Object[] a) {
return l1 + l2;
} }
private long result[] = new long[1];
private void test() { private void test() {
// For the array allocation, C1 emits a slow call into the runtime // For the array allocation, C1 emits a slow call into the runtime
// that deoptimizes the caller frame due to -XX:+DeoptimizeALot. // that deoptimizes the caller frame due to -XX:+DeoptimizeALot.
// The VerifyStack code then gets confused because the following // The VerifyStack code then gets confused because the following
// bytecode instruction is an invoke and the interpreter oop map // bytecode instruction is an invoke and the interpreter oop map
// generator reports the oop map after execution of that invoke. // generator reports the oop map after execution of that invoke.
method(new Object[0]); this.result[0] = method(1L, 2L, new Object[0]);
} }
public static void main(String[] args) { public static void main(String[] args) {