8019519: PPC64 (part 105): C interpreter: implement support for jvmti early return
Reviewed-by: sspitsyn, kvn
This commit is contained in:
parent
8cc4fad115
commit
6514fe6794
@ -35,6 +35,7 @@
|
|||||||
#include "oops/objArrayKlass.hpp"
|
#include "oops/objArrayKlass.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
|
#include "prims/jvmtiThreadState.hpp"
|
||||||
#include "runtime/biasedLocking.hpp"
|
#include "runtime/biasedLocking.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
@ -197,6 +198,10 @@
|
|||||||
!THREAD->pop_frame_in_process()) { \
|
!THREAD->pop_frame_in_process()) { \
|
||||||
goto handle_Pop_Frame; \
|
goto handle_Pop_Frame; \
|
||||||
} \
|
} \
|
||||||
|
if (THREAD->jvmti_thread_state() && \
|
||||||
|
THREAD->jvmti_thread_state()->is_earlyret_pending()) { \
|
||||||
|
goto handle_Early_Return; \
|
||||||
|
} \
|
||||||
opcode = *pc; \
|
opcode = *pc; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
@ -420,6 +425,10 @@
|
|||||||
if (THREAD->pop_frame_pending() && \
|
if (THREAD->pop_frame_pending() && \
|
||||||
!THREAD->pop_frame_in_process()) { \
|
!THREAD->pop_frame_in_process()) { \
|
||||||
goto handle_Pop_Frame; \
|
goto handle_Pop_Frame; \
|
||||||
|
} \
|
||||||
|
if (THREAD->jvmti_thread_state() && \
|
||||||
|
THREAD->jvmti_thread_state()->is_earlyret_pending()) { \
|
||||||
|
goto handle_Early_Return; \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the VM and check for pending exceptions
|
// Call the VM and check for pending exceptions
|
||||||
@ -783,7 +792,6 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
case popping_frame: {
|
case popping_frame: {
|
||||||
// returned from a java call to pop the frame, restart the call
|
// returned from a java call to pop the frame, restart the call
|
||||||
// clear the message so we don't confuse ourselves later
|
// clear the message so we don't confuse ourselves later
|
||||||
ShouldNotReachHere(); // we don't return this.
|
|
||||||
assert(THREAD->pop_frame_in_process(), "wrong frame pop state");
|
assert(THREAD->pop_frame_in_process(), "wrong frame pop state");
|
||||||
istate->set_msg(no_request);
|
istate->set_msg(no_request);
|
||||||
THREAD->clr_pop_frame_in_process();
|
THREAD->clr_pop_frame_in_process();
|
||||||
@ -811,6 +819,10 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
if (THREAD->pop_frame_pending() && !THREAD->pop_frame_in_process()) {
|
if (THREAD->pop_frame_pending() && !THREAD->pop_frame_in_process()) {
|
||||||
goto handle_Pop_Frame;
|
goto handle_Pop_Frame;
|
||||||
}
|
}
|
||||||
|
if (THREAD->jvmti_thread_state() &&
|
||||||
|
THREAD->jvmti_thread_state()->is_earlyret_pending()) {
|
||||||
|
goto handle_Early_Return;
|
||||||
|
}
|
||||||
|
|
||||||
if (THREAD->has_pending_exception()) goto handle_exception;
|
if (THREAD->has_pending_exception()) goto handle_exception;
|
||||||
// Update the pc by the saved amount of the invoke bytecode size
|
// Update the pc by the saved amount of the invoke bytecode size
|
||||||
@ -2708,14 +2720,12 @@ run:
|
|||||||
// No handler in this activation, unwind and try again
|
// No handler in this activation, unwind and try again
|
||||||
THREAD->set_pending_exception(except_oop(), NULL, 0);
|
THREAD->set_pending_exception(except_oop(), NULL, 0);
|
||||||
goto handle_return;
|
goto handle_return;
|
||||||
} /* handle_exception: */
|
} // handle_exception:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Return from an interpreter invocation with the result of the interpretation
|
// Return from an interpreter invocation with the result of the interpretation
|
||||||
// on the top of the Java Stack (or a pending exception)
|
// on the top of the Java Stack (or a pending exception)
|
||||||
|
|
||||||
handle_Pop_Frame:
|
handle_Pop_Frame: {
|
||||||
|
|
||||||
// We don't really do anything special here except we must be aware
|
// We don't really do anything special here except we must be aware
|
||||||
// that we can get here without ever locking the method (if sync).
|
// that we can get here without ever locking the method (if sync).
|
||||||
@ -2728,12 +2738,63 @@ handle_Pop_Frame:
|
|||||||
// Let interpreter (only) see the we're in the process of popping a frame
|
// Let interpreter (only) see the we're in the process of popping a frame
|
||||||
THREAD->set_pop_frame_in_process();
|
THREAD->set_pop_frame_in_process();
|
||||||
|
|
||||||
handle_return:
|
goto handle_return;
|
||||||
{
|
|
||||||
|
} // handle_Pop_Frame
|
||||||
|
|
||||||
|
// ForceEarlyReturn ends a method, and returns to the caller with a return value
|
||||||
|
// given by the invoker of the early return.
|
||||||
|
handle_Early_Return: {
|
||||||
|
|
||||||
|
istate->set_msg(early_return);
|
||||||
|
|
||||||
|
// Clear expression stack.
|
||||||
|
topOfStack = istate->stack_base() - Interpreter::stackElementWords;
|
||||||
|
|
||||||
|
JvmtiThreadState *ts = THREAD->jvmti_thread_state();
|
||||||
|
|
||||||
|
// Push the value to be returned.
|
||||||
|
switch (istate->method()->result_type()) {
|
||||||
|
case T_BOOLEAN:
|
||||||
|
case T_SHORT:
|
||||||
|
case T_BYTE:
|
||||||
|
case T_CHAR:
|
||||||
|
case T_INT:
|
||||||
|
SET_STACK_INT(->earlyret_value().i, 0);
|
||||||
|
MORE_STACK(1);
|
||||||
|
break;
|
||||||
|
case T_LONG:
|
||||||
|
SET_STACK_LONG(ts->earlyret_value().j, 1);
|
||||||
|
MORE_STACK(2);
|
||||||
|
break;
|
||||||
|
case T_FLOAT:
|
||||||
|
SET_STACK_FLOAT(ts->earlyret_value().f, 0);
|
||||||
|
MORE_STACK(1);
|
||||||
|
break;
|
||||||
|
case T_DOUBLE:
|
||||||
|
SET_STACK_DOUBLE(ts->earlyret_value().d, 1);
|
||||||
|
MORE_STACK(2);
|
||||||
|
break;
|
||||||
|
case T_ARRAY:
|
||||||
|
case T_OBJECT:
|
||||||
|
SET_STACK_OBJECT(ts->earlyret_oop(), 0);
|
||||||
|
MORE_STACK(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->clr_earlyret_value();
|
||||||
|
ts->set_earlyret_oop(NULL);
|
||||||
|
ts->clr_earlyret_pending();
|
||||||
|
|
||||||
|
// Fall through to handle_return.
|
||||||
|
|
||||||
|
} // handle_Early_Return
|
||||||
|
|
||||||
|
handle_return: {
|
||||||
DECACHE_STATE();
|
DECACHE_STATE();
|
||||||
|
|
||||||
bool suppress_error = istate->msg() == popping_frame;
|
bool suppress_error = istate->msg() == popping_frame || istate->msg() == early_return;
|
||||||
bool suppress_exit_event = THREAD->has_pending_exception() || suppress_error;
|
bool suppress_exit_event = THREAD->has_pending_exception() || istate->msg() == popping_frame;
|
||||||
Handle original_exception(THREAD, THREAD->pending_exception());
|
Handle original_exception(THREAD, THREAD->pending_exception());
|
||||||
Handle illegal_state_oop(THREAD, NULL);
|
Handle illegal_state_oop(THREAD, NULL);
|
||||||
|
|
||||||
@ -2946,7 +3007,6 @@ handle_return:
|
|||||||
THREAD->set_pending_exception(illegal_state_oop(), NULL, 0);
|
THREAD->set_pending_exception(illegal_state_oop(), NULL, 0);
|
||||||
else
|
else
|
||||||
THREAD->set_pending_exception(original_exception(), NULL, 0);
|
THREAD->set_pending_exception(original_exception(), NULL, 0);
|
||||||
istate->set_return_kind((Bytecodes::Code)opcode);
|
|
||||||
UPDATE_PC_AND_RETURN(0);
|
UPDATE_PC_AND_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2965,13 +3025,12 @@ handle_return:
|
|||||||
LOCALS_SLOT(METHOD->size_of_parameters() - 1));
|
LOCALS_SLOT(METHOD->size_of_parameters() - 1));
|
||||||
THREAD->set_popframe_condition_bit(JavaThread::popframe_force_deopt_reexecution_bit);
|
THREAD->set_popframe_condition_bit(JavaThread::popframe_force_deopt_reexecution_bit);
|
||||||
}
|
}
|
||||||
THREAD->clr_pop_frame_in_process();
|
} else {
|
||||||
|
istate->set_msg(return_from_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal return
|
// Normal return
|
||||||
// Advance the pc and return to frame manager
|
// Advance the pc and return to frame manager
|
||||||
istate->set_msg(return_from_method);
|
|
||||||
istate->set_return_kind((Bytecodes::Code)opcode);
|
|
||||||
UPDATE_PC_AND_RETURN(1);
|
UPDATE_PC_AND_RETURN(1);
|
||||||
} /* handle_return: */
|
} /* handle_return: */
|
||||||
|
|
||||||
@ -3246,7 +3305,6 @@ BytecodeInterpreter::print() {
|
|||||||
tty->print_cr("result_to_call._bcp_advance: %d ", this->_result._to_call._bcp_advance);
|
tty->print_cr("result_to_call._bcp_advance: %d ", this->_result._to_call._bcp_advance);
|
||||||
tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf);
|
tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf);
|
||||||
tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry);
|
tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry);
|
||||||
tty->print_cr("result_return_kind 0x%x ", (int) this->_result._return_kind);
|
|
||||||
tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link);
|
tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link);
|
||||||
tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp);
|
tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp);
|
||||||
tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base);
|
tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base);
|
||||||
|
@ -66,27 +66,26 @@ union VMJavaVal64 {
|
|||||||
typedef class BytecodeInterpreter* interpreterState;
|
typedef class BytecodeInterpreter* interpreterState;
|
||||||
|
|
||||||
struct call_message {
|
struct call_message {
|
||||||
class Method* _callee; /* method to call during call_method request */
|
class Method* _callee; // method to call during call_method request
|
||||||
address _callee_entry_point; /* address to jump to for call_method request */
|
address _callee_entry_point; // address to jump to for call_method request
|
||||||
int _bcp_advance; /* size of the invoke bytecode operation */
|
int _bcp_advance; // size of the invoke bytecode operation
|
||||||
};
|
};
|
||||||
|
|
||||||
struct osr_message {
|
struct osr_message {
|
||||||
address _osr_buf; /* the osr buffer */
|
address _osr_buf; // the osr buffer
|
||||||
address _osr_entry; /* the entry to the osr method */
|
address _osr_entry; // the entry to the osr method
|
||||||
};
|
};
|
||||||
|
|
||||||
struct osr_result {
|
struct osr_result {
|
||||||
nmethod* nm; /* osr nmethod */
|
nmethod* nm; // osr nmethod
|
||||||
address return_addr; /* osr blob return address */
|
address return_addr; // osr blob return address
|
||||||
};
|
};
|
||||||
|
|
||||||
// Result returned to frame manager
|
// Result returned to frame manager
|
||||||
union frame_manager_message {
|
union frame_manager_message {
|
||||||
call_message _to_call; /* describes callee */
|
call_message _to_call; // describes callee
|
||||||
Bytecodes::Code _return_kind; /* i_return, a_return, ... */
|
osr_message _osr; // describes the osr
|
||||||
osr_message _osr; /* describes the osr */
|
osr_result _osr_result; // result of OSR request
|
||||||
osr_result _osr_result; /* result of OSR request */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BytecodeInterpreter : StackObj {
|
class BytecodeInterpreter : StackObj {
|
||||||
@ -115,7 +114,8 @@ public:
|
|||||||
more_monitors, // need a new monitor
|
more_monitors, // need a new monitor
|
||||||
throwing_exception, // unwind stack and rethrow
|
throwing_exception, // unwind stack and rethrow
|
||||||
popping_frame, // unwind call and retry call
|
popping_frame, // unwind call and retry call
|
||||||
do_osr // request this invocation be OSR's
|
do_osr, // request this invocation be OSR's
|
||||||
|
early_return // early return as commanded by jvmti
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -216,8 +216,6 @@ inline void set_osr_entry(address entry) { _result._osr._osr_entry = entry; }
|
|||||||
inline int bcp_advance() { return _result._to_call._bcp_advance; }
|
inline int bcp_advance() { return _result._to_call._bcp_advance; }
|
||||||
inline void set_bcp_advance(int count) { _result._to_call._bcp_advance = count; }
|
inline void set_bcp_advance(int count) { _result._to_call._bcp_advance = count; }
|
||||||
|
|
||||||
inline void set_return_kind(Bytecodes::Code kind) { _result._return_kind = kind; }
|
|
||||||
|
|
||||||
inline interpreterState prev() { return _prev_link; }
|
inline interpreterState prev() { return _prev_link; }
|
||||||
|
|
||||||
inline intptr_t* stack() { return _stack; }
|
inline intptr_t* stack() { return _stack; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user