# HG changeset patch # User goetz # Date 1372843506 -7200 # Node ID bfd9d884693d71dfc1db0c49a559af36cd814333 # Parent 48b178ff07b689a761363189db7faea207132084 8019519: PPC64 (part 105): C interpreter: implement support for jvmti early return. Reviewed-by: sspitsyn, kvn diff -r 48b178ff07b6 -r bfd9d884693d src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Jul 03 01:41:42 2013 +0200 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Jul 03 11:25:06 2013 +0200 @@ -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 @@ 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 @@ 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 @@ // 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: - - // 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(); - -handle_return: - { + 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. + + 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(); + + 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 @@ 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 @@ 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 @@ 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); diff -r 48b178ff07b6 -r bfd9d884693d src/share/vm/interpreter/bytecodeInterpreter.hpp --- a/src/share/vm/interpreter/bytecodeInterpreter.hpp Wed Jul 03 01:41:42 2013 +0200 +++ b/src/share/vm/interpreter/bytecodeInterpreter.hpp Wed Jul 03 11:25:06 2013 +0200 @@ -66,27 +66,26 @@ 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 @@ 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 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; }