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/oop.inline.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "prims/jvmtiThreadState.hpp"
|
||||
#include "runtime/biasedLocking.hpp"
|
||||
#include "runtime/frame.inline.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
@ -197,6 +198,10 @@
|
||||
!THREAD->pop_frame_in_process()) { \
|
||||
goto handle_Pop_Frame; \
|
||||
} \
|
||||
if (THREAD->jvmti_thread_state() && \
|
||||
THREAD->jvmti_thread_state()->is_earlyret_pending()) { \
|
||||
goto handle_Early_Return; \
|
||||
} \
|
||||
opcode = *pc; \
|
||||
} \
|
||||
} \
|
||||
@ -411,21 +416,25 @@
|
||||
CACHE_LOCALS();
|
||||
|
||||
// Call the VM don't check for pending exceptions
|
||||
#define CALL_VM_NOCHECK(func) \
|
||||
DECACHE_STATE(); \
|
||||
SET_LAST_JAVA_FRAME(); \
|
||||
func; \
|
||||
RESET_LAST_JAVA_FRAME(); \
|
||||
CACHE_STATE(); \
|
||||
if (THREAD->pop_frame_pending() && \
|
||||
!THREAD->pop_frame_in_process()) { \
|
||||
goto handle_Pop_Frame; \
|
||||
}
|
||||
#define CALL_VM_NOCHECK(func) \
|
||||
DECACHE_STATE(); \
|
||||
SET_LAST_JAVA_FRAME(); \
|
||||
func; \
|
||||
RESET_LAST_JAVA_FRAME(); \
|
||||
CACHE_STATE(); \
|
||||
if (THREAD->pop_frame_pending() && \
|
||||
!THREAD->pop_frame_in_process()) { \
|
||||
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
|
||||
#define CALL_VM(func, label) { \
|
||||
CALL_VM_NOCHECK(func); \
|
||||
if (THREAD->has_pending_exception()) goto label; \
|
||||
#define CALL_VM(func, label) { \
|
||||
CALL_VM_NOCHECK(func); \
|
||||
if (THREAD->has_pending_exception()) goto label; \
|
||||
}
|
||||
|
||||
/*
|
||||
@ -783,7 +792,6 @@ BytecodeInterpreter::run(interpreterState istate) {
|
||||
case popping_frame: {
|
||||
// returned from a java call to pop the frame, restart the call
|
||||
// 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");
|
||||
istate->set_msg(no_request);
|
||||
THREAD->clr_pop_frame_in_process();
|
||||
@ -811,6 +819,10 @@ BytecodeInterpreter::run(interpreterState istate) {
|
||||
if (THREAD->pop_frame_pending() && !THREAD->pop_frame_in_process()) {
|
||||
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;
|
||||
// Update the pc by the saved amount of the invoke bytecode size
|
||||
@ -2708,32 +2720,81 @@ run:
|
||||
// No handler in this activation, unwind and try again
|
||||
THREAD->set_pending_exception(except_oop(), NULL, 0);
|
||||
goto handle_return;
|
||||
} /* handle_exception: */
|
||||
|
||||
|
||||
} // handle_exception:
|
||||
|
||||
// Return from an interpreter invocation with the result of the interpretation
|
||||
// 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
|
||||
// that we can get here without ever locking the method (if sync).
|
||||
// Also we skip the notification of the exit.
|
||||
// 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).
|
||||
// Also we skip the notification of the exit.
|
||||
|
||||
istate->set_msg(popping_frame);
|
||||
// Clear pending so while the pop is in process
|
||||
// we don't start another one if a call_vm is done.
|
||||
THREAD->clr_pop_frame_pending();
|
||||
// Let interpreter (only) see the we're in the process of popping a frame
|
||||
THREAD->set_pop_frame_in_process();
|
||||
istate->set_msg(popping_frame);
|
||||
// Clear pending so while the pop is in process
|
||||
// we don't start another one if a call_vm is done.
|
||||
THREAD->clr_pop_frame_pending();
|
||||
// Let interpreter (only) see the we're in the process of popping a frame
|
||||
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();
|
||||
|
||||
bool suppress_error = istate->msg() == popping_frame;
|
||||
bool suppress_exit_event = THREAD->has_pending_exception() || suppress_error;
|
||||
bool suppress_error = istate->msg() == popping_frame || istate->msg() == early_return;
|
||||
bool suppress_exit_event = THREAD->has_pending_exception() || istate->msg() == popping_frame;
|
||||
Handle original_exception(THREAD, THREAD->pending_exception());
|
||||
Handle illegal_state_oop(THREAD, NULL);
|
||||
|
||||
@ -2946,7 +3007,6 @@ handle_return:
|
||||
THREAD->set_pending_exception(illegal_state_oop(), NULL, 0);
|
||||
else
|
||||
THREAD->set_pending_exception(original_exception(), NULL, 0);
|
||||
istate->set_return_kind((Bytecodes::Code)opcode);
|
||||
UPDATE_PC_AND_RETURN(0);
|
||||
}
|
||||
|
||||
@ -2965,13 +3025,12 @@ handle_return:
|
||||
LOCALS_SLOT(METHOD->size_of_parameters() - 1));
|
||||
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
|
||||
// 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);
|
||||
} /* 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("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("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("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp);
|
||||
tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base);
|
||||
|
@ -66,27 +66,26 @@ union VMJavaVal64 {
|
||||
typedef class BytecodeInterpreter* interpreterState;
|
||||
|
||||
struct call_message {
|
||||
class Method* _callee; /* method to call during call_method request */
|
||||
address _callee_entry_point; /* address to jump to for call_method request */
|
||||
int _bcp_advance; /* size of the invoke bytecode operation */
|
||||
class Method* _callee; // method to call during call_method request
|
||||
address _callee_entry_point; // address to jump to for call_method request
|
||||
int _bcp_advance; // size of the invoke bytecode operation
|
||||
};
|
||||
|
||||
struct osr_message {
|
||||
address _osr_buf; /* the osr buffer */
|
||||
address _osr_entry; /* the entry to the osr method */
|
||||
address _osr_buf; // the osr buffer
|
||||
address _osr_entry; // the entry to the osr method
|
||||
};
|
||||
|
||||
struct osr_result {
|
||||
nmethod* nm; /* osr nmethod */
|
||||
address return_addr; /* osr blob return address */
|
||||
nmethod* nm; // osr nmethod
|
||||
address return_addr; // osr blob return address
|
||||
};
|
||||
|
||||
// Result returned to frame manager
|
||||
union frame_manager_message {
|
||||
call_message _to_call; /* describes callee */
|
||||
Bytecodes::Code _return_kind; /* i_return, a_return, ... */
|
||||
osr_message _osr; /* describes the osr */
|
||||
osr_result _osr_result; /* result of OSR request */
|
||||
call_message _to_call; // describes callee
|
||||
osr_message _osr; // describes the osr
|
||||
osr_result _osr_result; // result of OSR request
|
||||
};
|
||||
|
||||
class BytecodeInterpreter : StackObj {
|
||||
@ -115,7 +114,8 @@ public:
|
||||
more_monitors, // need a new monitor
|
||||
throwing_exception, // unwind stack and rethrow
|
||||
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:
|
||||
@ -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 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 intptr_t* stack() { return _stack; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user