src/share/vm/interpreter/bytecodeInterpreter.cpp
Print this page
rev 4869 : 8019519: PPC64 (part 105): C interpreter: implement support for jvmti early return.
@@ -34,10 +34,11 @@
#include "memory/resourceArea.hpp"
#include "oops/methodCounters.hpp"
#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"
#include "runtime/interfaceSupport.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -196,10 +197,14 @@
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; \
+ } \
opcode = *pc; \
} \
} \
}
#else
@@ -419,10 +424,14 @@
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); \
@@ -818,10 +827,14 @@
#endif // HACK
// returned from a java call, continue executing.
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
UPDATE_PC(istate->bcp_advance());
goto run;
@@ -2721,12 +2734,10 @@
// No handler in this activation, unwind and try again
THREAD->set_pending_exception(except_oop(), NULL, 0);
goto handle_return;
} /* 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:
@@ -2739,16 +2750,62 @@
// 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;
+
+// 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;
+
+ // 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(THREAD->jvmti_thread_state()->earlyret_value().i, 0);
+ MORE_STACK(1);
+ break;
+ case T_LONG:
+ SET_STACK_LONG(THREAD->jvmti_thread_state()->earlyret_value().j, 1);
+ MORE_STACK(2);
+ break;
+ case T_FLOAT:
+ SET_STACK_FLOAT(THREAD->jvmti_thread_state()->earlyret_value().f, 0);
+ MORE_STACK(1);
+ break;
+ case T_DOUBLE:
+ SET_STACK_DOUBLE(THREAD->jvmti_thread_state()->earlyret_value().d, 1);
+ MORE_STACK(2);
+ break;
+ case T_ARRAY:
+ case T_OBJECT:
+ SET_STACK_OBJECT(THREAD->jvmti_thread_state()->earlyret_oop(), 0);
+ MORE_STACK(1);
+ break;
+ }
+
+ THREAD->jvmti_thread_state()->clr_earlyret_value();
+ THREAD->jvmti_thread_state()->set_earlyret_oop(NULL);
+ THREAD->jvmti_thread_state()->clr_earlyret_pending();
+
+ // Fall through to handle_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);
// We'd like a HandleMark here to prevent any subsequent HandleMarkCleaner
// in any following VM entries from freeing our live handles, but illegal_state_oop
@@ -2957,11 +3014,10 @@
istate->set_msg(throwing_exception);
if (illegal_state_oop() != NULL)
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);
}
if (istate->msg() == popping_frame) {
// Make it simpler on the assembly code and set the message for the frame pop.
@@ -2976,17 +3032,16 @@
//
THREAD->popframe_preserve_args(in_ByteSize(METHOD->size_of_parameters() * wordSize),
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: */
// This is really a fatal error return