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