changeset 9046:c6a1ffc707ff

Comments and #ifdef GRAAL for recent changes to C++ code for calling nmethods directly.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 12 Apr 2013 17:22:54 +0200
parents 9a3e25e270a0
children 1946c86f8842
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java src/cpu/sparc/vm/interpreter_sparc.cpp src/cpu/sparc/vm/sharedRuntime_sparc.cpp src/cpu/x86/vm/interpreterGenerator_x86.hpp src/cpu/x86/vm/sharedRuntime_x86_64.cpp src/cpu/x86/vm/templateInterpreter_x86_64.cpp src/share/vm/code/nmethod.cpp src/share/vm/interpreter/abstractInterpreter.hpp src/share/vm/interpreter/interpreter.cpp src/share/vm/interpreter/templateInterpreter.cpp src/share/vm/oops/method.cpp
diffstat 11 files changed, 60 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 12 06:19:35 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 12 17:22:54 2013 +0200
@@ -170,5 +170,12 @@
         return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod);
     }
 
+    /**
+     * Direct call to the given nativeMethod with three object arguments and an object return value.
+     * This method does not have an implementation on the C++ side, but its entry points (from
+     * interpreter and from compiled code) are directly pointing to a manually generated assembly
+     * stub that does the necessary argument shuffling and a tail call via an indirect jump to the
+     * verified entry point of the given native method.
+     */
     private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod);
 }
--- a/src/cpu/sparc/vm/interpreter_sparc.cpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/cpu/sparc/vm/interpreter_sparc.cpp	Fri Apr 12 17:22:54 2013 +0200
@@ -381,7 +381,9 @@
     case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
     case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false);  break;
     case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);   break;
+#ifdef GRAAL
     case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry();   break;
+#endif
     case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();        break;
     case Interpreter::accessor               : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry();     break;
     case Interpreter::abstract               : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry();     break;
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Apr 12 17:22:54 2013 +0200
@@ -1917,7 +1917,6 @@
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
                                                 BasicType ret_type) {
-  assert (method->intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "not yet ported");
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
     intptr_t start = (intptr_t)__ pc();
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Fri Apr 12 17:22:54 2013 +0200
@@ -36,7 +36,9 @@
 
   address generate_normal_entry(bool synchronized);
   address generate_native_entry(bool synchronized);
+#ifdef GRAAL
   address generate_execute_compiled_method_entry();
+#endif
   address generate_abstract_entry(void);
   address generate_math_entry(AbstractInterpreter::MethodKind kind);
   address generate_empty_entry(void);
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Apr 12 17:22:54 2013 +0200
@@ -1670,10 +1670,16 @@
   verify_oop_args(masm, method, sig_bt, regs);
   vmIntrinsics::ID iid = method->intrinsic_id();
 
+#ifdef GRAAL
   if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // We are called from compiled code here. The three object arguments
+    // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The
+    // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail
+    // call to its verified entry point.
     __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
     return;
   }
+#endif
 
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Fri Apr 12 17:22:54 2013 +0200
@@ -873,6 +873,8 @@
   return generate_accessor_entry();
 }
 
+#ifdef GRAAL
+
 // Interpreter stub for calling a compiled method with 3 object arguments
 address InterpreterGenerator::generate_execute_compiled_method_entry() {
   address entry_point = __ pc();
@@ -891,14 +893,27 @@
   // as far as the placement of the call instruction
   __ push(rax);
 
+  // Move first object argument from interpreter calling convention to compiled
+  // code calling convention.
   __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5));
+
+  // Move second object argument.
   __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4));
+
+  // Move third object argument.
   __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3));
+
+  // Load the raw pointer to the nmethod.
   __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize));
+
+  // Perform a tail call to the verified entry point of the nmethod.
   __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+
   return entry_point;
 }
 
+#endif
+
 // Interpreter stub for calling a native method. (asm interpreter)
 // This sets up a somewhat different looking stack for calling the
 // native method than the typical interpreter frame setup.
@@ -1586,7 +1601,9 @@
   switch (kind) {
   case Interpreter::zerolocals             :                                                                             break;
   case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
+#ifdef GRAAL
   case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break;
+#endif
   case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break;
   case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);  break;
   case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();       break;
--- a/src/share/vm/code/nmethod.cpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/share/vm/code/nmethod.cpp	Fri Apr 12 17:22:54 2013 +0200
@@ -1307,9 +1307,12 @@
   }
 
 #ifdef GRAAL
-    if (_graal_installed_code != NULL) {
-      _graal_installed_code = NULL;
-    }
+  // The method can only be unloaded after the pointer to the installed code
+  // Java wrapper is no longer alive. Here we need to clear out this weak
+  // reference to the dead object.
+  if (_graal_installed_code != NULL) {
+    _graal_installed_code = NULL;
+  }
 #endif
 
   // Make the class unloaded - i.e., change state and notify sweeper
@@ -1396,14 +1399,14 @@
     // The caller can be calling the method statically or through an inline
     // cache call.
     if (!is_osr_method() && !is_not_entrant()) {
+      address stub = SharedRuntime::get_handle_wrong_method_stub();
+#ifdef GRAAL
       if (_graal_installed_code != NULL && !HotSpotInstalledCode::isDefault(_graal_installed_code)) {
         // This was manually installed machine code. Patch entry with stub that throws an exception.
-        NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
-                    SharedRuntime::get_deoptimized_installed_code_stub());
-      } else {
-        NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
-                    SharedRuntime::get_handle_wrong_method_stub());
+        stub = SharedRuntime::get_deoptimized_installed_code_stub();
       }
+#endif
+      NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub);
     }
 
     if (is_in_use()) {
--- a/src/share/vm/interpreter/abstractInterpreter.hpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp	Fri Apr 12 17:22:54 2013 +0200
@@ -85,7 +85,9 @@
     zerolocals_synchronized,                                    // method needs locals initialization & is synchronized
     native,                                                     // native method
     native_synchronized,                                        // native method & is synchronized
+#ifdef GRAAL
     execute_compiled_method,                                    // direct call to compiled method address
+#endif
     empty,                                                      // empty method (code: _return)
     accessor,                                                   // accessor method (code: _aload_0, _getfield, _(a|i)return)
     abstract,                                                   // abstract method (throws an AbstractMethodException)
--- a/src/share/vm/interpreter/interpreter.cpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/share/vm/interpreter/interpreter.cpp	Fri Apr 12 17:22:54 2013 +0200
@@ -188,9 +188,13 @@
   // Method handle primitive?
   if (m->is_method_handle_intrinsic()) {
     vmIntrinsics::ID id = m->intrinsic_id();
+#ifdef GRAAL
     if (id == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+      // Special method kind for directly executing the verified entry point
+      // of a given nmethod.
       return AbstractInterpreter::execute_compiled_method;
     }
+#endif
     assert(MethodHandles::is_signature_polymorphic(id), "must match an intrinsic");
     MethodKind kind = (MethodKind)( method_handle_invoke_FIRST +
                                     ((int)id - vmIntrinsics::FIRST_MH_SIG_POLY) );
@@ -290,7 +294,9 @@
     case zerolocals_synchronized: tty->print("zerolocals_synchronized"); break;
     case native                 : tty->print("native"                 ); break;
     case native_synchronized    : tty->print("native_synchronized"    ); break;
+#ifdef GRAAL
     case execute_compiled_method: tty->print("execute_compiled_method"); break;
+#endif
     case empty                  : tty->print("empty"                  ); break;
     case accessor               : tty->print("accessor"               ); break;
     case abstract               : tty->print("abstract"               ); break;
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Fri Apr 12 17:22:54 2013 +0200
@@ -360,7 +360,9 @@
   method_entry(zerolocals)
   method_entry(zerolocals_synchronized)
   method_entry(empty)
+#ifdef GRAAL
   method_entry(execute_compiled_method)
+#endif
   method_entry(accessor)
   method_entry(abstract)
   method_entry(java_lang_math_sin  )
--- a/src/share/vm/oops/method.cpp	Fri Apr 12 06:19:35 2013 +0200
+++ b/src/share/vm/oops/method.cpp	Fri Apr 12 17:22:54 2013 +0200
@@ -850,10 +850,15 @@
   (void) make_adapters(h_method, CHECK);
 
   // ONLY USE the h_method now as make_adapter may have blocked
+
+#ifdef GRAAL
+  // Check for special intrinsic that executes a compiled method.
   if (h_method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // Actively install the stub for calling the intrinsic from compiled code.
     CompileBroker::compile_method(h_method, InvocationEntryBci, CompLevel_highest_tier,
                                   methodHandle(), CompileThreshold, "executeCompiledMethod", CHECK);
   }
+#endif
 }
 
 address Method::make_adapters(methodHandle mh, TRAPS) {