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:
Changpeng Fang 2009-07-31 17:12:33 -07:00
parent f2ea22a547
commit ae00753bf7
29 changed files with 465 additions and 241 deletions

View file

@ -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