mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
Developed a reexecute logic for the interpreter to reexecute the bytecode when deopt happens Reviewed-by: kvn, never, jrose, twisti
This commit is contained in:
parent
f2ea22a547
commit
ae00753bf7
29 changed files with 465 additions and 241 deletions
|
@ -284,76 +284,19 @@ static BasicType constant_pool_type(methodOop method, int index) {
|
|||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Deoptimization support
|
||||
|
||||
// If deoptimization happens, this method returns the point where to continue in
|
||||
// interpreter. For calls (invokexxxx, newxxxx) the continuation is at next
|
||||
// bci and the top of stack is in eax/edx/FPU tos.
|
||||
// For putfield/getfield, put/getstatic, the continuation is at the same
|
||||
// bci and the TOS is on stack.
|
||||
|
||||
// Note: deopt_entry(type, 0) means reexecute bytecode
|
||||
// deopt_entry(type, length) means continue at next bytecode
|
||||
|
||||
address AbstractInterpreter::continuation_for(methodOop method, address bcp, int callee_parameters, bool is_top_frame, bool& use_next_mdp) {
|
||||
// If deoptimization happens, this function returns the point of next bytecode to continue execution
|
||||
address AbstractInterpreter::deopt_continue_after_entry(methodOop method, address bcp, int callee_parameters, bool is_top_frame) {
|
||||
assert(method->contains(bcp), "just checkin'");
|
||||
Bytecodes::Code code = Bytecodes::java_code_at(bcp);
|
||||
assert(!Interpreter::bytecode_should_reexecute(code), "should not reexecute");
|
||||
int bci = method->bci_from(bcp);
|
||||
int length = -1; // initial value for debugging
|
||||
// compute continuation length
|
||||
length = Bytecodes::length_at(bcp);
|
||||
// compute result type
|
||||
BasicType type = T_ILLEGAL;
|
||||
// when continuing after a compiler safepoint, re-execute the bytecode
|
||||
// (an invoke is continued after the safepoint)
|
||||
use_next_mdp = true;
|
||||
|
||||
switch (code) {
|
||||
case Bytecodes::_lookupswitch:
|
||||
case Bytecodes::_tableswitch:
|
||||
case Bytecodes::_fast_binaryswitch:
|
||||
case Bytecodes::_fast_linearswitch:
|
||||
// recompute condtional expression folded into _if<cond>
|
||||
case Bytecodes::_lcmp :
|
||||
case Bytecodes::_fcmpl :
|
||||
case Bytecodes::_fcmpg :
|
||||
case Bytecodes::_dcmpl :
|
||||
case Bytecodes::_dcmpg :
|
||||
case Bytecodes::_ifnull :
|
||||
case Bytecodes::_ifnonnull :
|
||||
case Bytecodes::_goto :
|
||||
case Bytecodes::_goto_w :
|
||||
case Bytecodes::_ifeq :
|
||||
case Bytecodes::_ifne :
|
||||
case Bytecodes::_iflt :
|
||||
case Bytecodes::_ifge :
|
||||
case Bytecodes::_ifgt :
|
||||
case Bytecodes::_ifle :
|
||||
case Bytecodes::_if_icmpeq :
|
||||
case Bytecodes::_if_icmpne :
|
||||
case Bytecodes::_if_icmplt :
|
||||
case Bytecodes::_if_icmpge :
|
||||
case Bytecodes::_if_icmpgt :
|
||||
case Bytecodes::_if_icmple :
|
||||
case Bytecodes::_if_acmpeq :
|
||||
case Bytecodes::_if_acmpne :
|
||||
// special cases
|
||||
case Bytecodes::_getfield :
|
||||
case Bytecodes::_putfield :
|
||||
case Bytecodes::_getstatic :
|
||||
case Bytecodes::_putstatic :
|
||||
case Bytecodes::_aastore :
|
||||
// reexecute the operation and TOS value is on stack
|
||||
assert(is_top_frame, "must be top frame");
|
||||
use_next_mdp = false;
|
||||
return Interpreter::deopt_entry(vtos, 0);
|
||||
break;
|
||||
|
||||
#ifdef COMPILER1
|
||||
case Bytecodes::_athrow :
|
||||
assert(is_top_frame, "must be top frame");
|
||||
use_next_mdp = false;
|
||||
return Interpreter::rethrow_exception_entry();
|
||||
break;
|
||||
#endif /* COMPILER1 */
|
||||
|
||||
case Bytecodes::_invokevirtual :
|
||||
case Bytecodes::_invokespecial :
|
||||
case Bytecodes::_invokestatic :
|
||||
|
@ -392,6 +335,70 @@ address AbstractInterpreter::continuation_for(methodOop method, address bcp, int
|
|||
: Interpreter::return_entry(as_TosState(type), length);
|
||||
}
|
||||
|
||||
// If deoptimization happens, this function returns the point where the interpreter reexecutes
|
||||
// the bytecode.
|
||||
// Note: Bytecodes::_athrow is a special case in that it does not return
|
||||
// Interpreter::deopt_entry(vtos, 0) like others
|
||||
address AbstractInterpreter::deopt_reexecute_entry(methodOop method, address bcp) {
|
||||
assert(method->contains(bcp), "just checkin'");
|
||||
Bytecodes::Code code = Bytecodes::java_code_at(bcp);
|
||||
#ifdef COMPILER1
|
||||
if(code == Bytecodes::_athrow ) {
|
||||
return Interpreter::rethrow_exception_entry();
|
||||
}
|
||||
#endif /* COMPILER1 */
|
||||
return Interpreter::deopt_entry(vtos, 0);
|
||||
}
|
||||
|
||||
// If deoptimization happens, the interpreter should reexecute these bytecodes.
|
||||
// This function mainly helps the compilers to set up the reexecute bit.
|
||||
bool AbstractInterpreter::bytecode_should_reexecute(Bytecodes::Code code) {
|
||||
switch (code) {
|
||||
case Bytecodes::_lookupswitch:
|
||||
case Bytecodes::_tableswitch:
|
||||
case Bytecodes::_fast_binaryswitch:
|
||||
case Bytecodes::_fast_linearswitch:
|
||||
// recompute condtional expression folded into _if<cond>
|
||||
case Bytecodes::_lcmp :
|
||||
case Bytecodes::_fcmpl :
|
||||
case Bytecodes::_fcmpg :
|
||||
case Bytecodes::_dcmpl :
|
||||
case Bytecodes::_dcmpg :
|
||||
case Bytecodes::_ifnull :
|
||||
case Bytecodes::_ifnonnull :
|
||||
case Bytecodes::_goto :
|
||||
case Bytecodes::_goto_w :
|
||||
case Bytecodes::_ifeq :
|
||||
case Bytecodes::_ifne :
|
||||
case Bytecodes::_iflt :
|
||||
case Bytecodes::_ifge :
|
||||
case Bytecodes::_ifgt :
|
||||
case Bytecodes::_ifle :
|
||||
case Bytecodes::_if_icmpeq :
|
||||
case Bytecodes::_if_icmpne :
|
||||
case Bytecodes::_if_icmplt :
|
||||
case Bytecodes::_if_icmpge :
|
||||
case Bytecodes::_if_icmpgt :
|
||||
case Bytecodes::_if_icmple :
|
||||
case Bytecodes::_if_acmpeq :
|
||||
case Bytecodes::_if_acmpne :
|
||||
// special cases
|
||||
case Bytecodes::_getfield :
|
||||
case Bytecodes::_putfield :
|
||||
case Bytecodes::_getstatic :
|
||||
case Bytecodes::_putstatic :
|
||||
case Bytecodes::_aastore :
|
||||
#ifdef COMPILER1
|
||||
//special case of reexecution
|
||||
case Bytecodes::_athrow :
|
||||
#endif
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
|
||||
// Quick & dirty stack overflow checking: bang the stack & handle trap.
|
||||
// Note that we do the banging after the frame is setup, since the exception
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue