changeset 5246:8bf2c37c46c4

added RiCompiledMethod.executeVarargs(Object...) to support compiling and calling arbitrary Java methods
author Doug Simon <doug.simon@oracle.com>
date Tue, 17 Apr 2012 13:52:38 +0200
parents 71ac4221b1b0
children 62bbfd78c703
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotCompiledMethod.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiCompiledMethod.java src/share/vm/graal/graalCompilerToVM.cpp
diffstat 6 files changed, 137 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Apr 17 13:38:28 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Apr 17 13:52:38 2012 +0200
@@ -113,6 +113,8 @@
 
     Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
 
+    Object executeCompiledMethodVarargs(HotSpotCompiledMethod method, Object... args);
+
     int RiMethod_vtableEntryOffset(HotSpotMethodResolved method);
 
     long[] getDeoptedLeafGraphIds();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Apr 17 13:38:28 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Apr 17 13:52:38 2012 +0200
@@ -163,6 +163,9 @@
     public native Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
 
     @Override
+    public native Object executeCompiledMethodVarargs(HotSpotCompiledMethod method, Object... args);
+
+    @Override
     public native int RiMethod_vtableEntryOffset(HotSpotMethodResolved method);
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotCompiledMethod.java	Tue Apr 17 13:38:28 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotCompiledMethod.java	Tue Apr 17 13:52:38 2012 +0200
@@ -67,4 +67,24 @@
         assert !Modifier.isStatic(method.accessFlags()) || method.signature().argumentKindAt(2, false) == CiKind.Object;
         return compiler.getVMEntries().executeCompiledMethod(this, arg1, arg2, arg3);
     }
+
+    private boolean checkArgs(Object... args) {
+        CiKind[] sig = CiUtil.signatureToKinds(method);
+        assert args.length == sig.length : CiUtil.format("%H.%n(%p): expected ", method) + sig.length + " args, got " + args.length;
+        for (int i = 0; i < sig.length; i++) {
+            Object arg = args[i];
+            if (arg == null) {
+                assert sig[i].isObject() : CiUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i];
+            } else if (!sig[i].isObject()) {
+                assert sig[i].toUnboxedJavaClass() == arg.getClass() : CiUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass();
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public Object executeVarargs(Object... args) {
+        assert checkArgs(args);
+        return compiler.getVMEntries().executeCompiledMethodVarargs(this, args);
+    }
 }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Tue Apr 17 13:38:28 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Tue Apr 17 13:52:38 2012 +0200
@@ -46,6 +46,11 @@
         return arg1 + " " + arg2 + " " + arg3;
     }
 
+    Object f1;
+    public Object testMethodVirtual(Object arg1, Object arg2, Object arg3) {
+        return f1 + " " + arg1 + " " + arg2 + " " + arg3;
+    }
+
     @Test
     public void test1() {
         Method method = getMethod("testMethod");
@@ -71,7 +76,37 @@
         } catch (MethodInvalidatedException t) {
             Assert.fail("method invalidated");
         }
+    }
 
+    @Test
+    public void test3() {
+        Method method = getMethod("testMethod");
+        final StructuredGraph graph = parse(method);
+        final RiResolvedMethod riMethod = runtime.getRiMethod(method);
+        CiTargetMethod targetMethod = runtime.compile(riMethod, graph);
+        RiCompiledMethod compiledMethod = runtime.addMethod(riMethod, targetMethod);
+        try {
+            Object result = compiledMethod.executeVarargs("1", "2", "3");
+            Assert.assertEquals("1 2 3", result);
+        } catch (MethodInvalidatedException t) {
+            Assert.fail("method invalidated");
+        }
+    }
+
+    @Test
+    public void test4() {
+        Method method = getMethod("testMethodVirtual");
+        final StructuredGraph graph = parse(method);
+        final RiResolvedMethod riMethod = runtime.getRiMethod(method);
+        CiTargetMethod targetMethod = runtime.compile(riMethod, graph);
+        RiCompiledMethod compiledMethod = runtime.addMethod(riMethod, targetMethod);
+        try {
+            f1 = "0";
+            Object result = compiledMethod.executeVarargs(this, "1", "2", "3");
+            Assert.assertEquals("0 1 2 3", result);
+        } catch (MethodInvalidatedException t) {
+            Assert.fail("method invalidated");
+        }
     }
 
     @Test
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiCompiledMethod.java	Tue Apr 17 13:38:28 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiCompiledMethod.java	Tue Apr 17 13:52:38 2012 +0200
@@ -44,4 +44,6 @@
     boolean isValid();
 
     Object execute(Object arg1, Object arg2, Object arg3);
+
+    Object executeVarargs(Object... args);
 }
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Apr 17 13:38:28 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Tue Apr 17 13:52:38 2012 +0200
@@ -966,6 +966,80 @@
   return JNIHandles::make_local(element);
 }
 
+class JavaArgumentPusher : public SignatureIterator {
+ protected:
+  JavaCallArguments*  _jca;
+  arrayOop _args;
+  int _index;
+
+  oop next_arg(BasicType expectedType) {
+    assert(_index < _args->length(), "out of bounds");
+    oop arg = ((oop*) _args->base(T_OBJECT))[_index++];
+    assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
+    return arg;
+  }
+
+ public:
+  JavaArgumentPusher(Symbol* signature, JavaCallArguments*  jca, arrayOop args, bool is_static) : SignatureIterator(signature) {
+    this->_return_type = T_ILLEGAL;
+    _jca = jca;
+    _index = 0;
+    _args = args;
+    if (!is_static) {
+      _jca->push_oop(next_arg(T_OBJECT));
+    }
+    iterate();
+    assert(_index == args->length(), "arg count mismatch with signature");
+  }
+
+  inline void do_bool()   { if (!is_return_type()) _jca->push_int(next_arg(T_BOOLEAN)->bool_field(java_lang_boxing_object::value_offset_in_bytes(T_BOOLEAN))); }
+  inline void do_char()   { if (!is_return_type()) _jca->push_int(next_arg(T_CHAR)->char_field(java_lang_boxing_object::value_offset_in_bytes(T_CHAR))); }
+  inline void do_short()  { if (!is_return_type()) _jca->push_int(next_arg(T_SHORT)->short_field(java_lang_boxing_object::value_offset_in_bytes(T_SHORT))); }
+  inline void do_byte()   { if (!is_return_type()) _jca->push_int(next_arg(T_BYTE)->byte_field(java_lang_boxing_object::value_offset_in_bytes(T_BYTE))); }
+  inline void do_int()    { if (!is_return_type()) _jca->push_int(next_arg(T_INT)->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT))); }
+
+  inline void do_long()   { if (!is_return_type()) _jca->push_long(next_arg(T_LONG)->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); }
+  inline void do_float()  { if (!is_return_type()) _jca->push_float(next_arg(T_FLOAT)->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT))); }
+  inline void do_double() { if (!is_return_type()) _jca->push_double(next_arg(T_DOUBLE)->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); }
+
+  inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_array(int begin, int end)  { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_void()                     { }
+};
+
+// public Object executeCompiledMethodVarargs(HotSpotCompiledMethod method, Object... args);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_executeCompiledMethodVarargs(JNIEnv *env, jobject, jobject method, jobject args) {
+  TRACE_graal_3("CompilerToVM::executeCompiledMethod");
+
+  VM_ENTRY_MARK;
+  ResourceMark rm;
+  HandleMark hm;
+
+  assert(method != NULL, "just checking");
+  methodHandle mh = getMethodFromHotSpotMethod(HotSpotCompiledMethod::method(method));
+  Symbol* signature = mh->signature();
+  JavaCallArguments jca;
+
+  JavaArgumentPusher jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
+  JavaValue result(jap.get_ret_type());
+
+  nmethod* nm = (nmethod*) HotSpotCompiledMethod::nmethod(method);
+  if (nm == NULL || !nm->is_alive()) {
+    THROW_0(vmSymbols::MethodInvalidatedException());
+  }
+  JavaCalls::call(&result, mh, nm, &jca, CHECK_NULL);
+
+  if (jap.get_ret_type() == T_VOID) {
+    return NULL;
+  } else if (jap.get_ret_type() == T_OBJECT) {
+    return JNIHandles::make_local((oop) result.get_jobject());
+  } else {
+    oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL);
+    return JNIHandles::make_local(o);
+  }
+}
+
 // public Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_executeCompiledMethod(JNIEnv *env, jobject, jobject method, jobject arg1, jobject arg2, jobject arg3) {
   TRACE_graal_3("CompilerToVM::executeCompiledMethod");
@@ -1086,6 +1160,7 @@
   {CC"disassembleJava",                   CC"("RESOLVED_METHOD")"STRING,                        FN_PTR(disassembleJava)},
   {CC"RiMethod_toStackTraceElement",      CC"("RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT,          FN_PTR(RiMethod_1toStackTraceElement)},
   {CC"executeCompiledMethod",             CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT,    FN_PTR(executeCompiledMethod)},
+  {CC"executeCompiledMethodVarargs",      CC"("HS_COMP_METHOD "["OBJECT")"OBJECT,               FN_PTR(executeCompiledMethodVarargs)},
   {CC"RiMethod_vtableEntryOffset",        CC"("RESOLVED_METHOD")I",                             FN_PTR(RiMethod_vtableEntryOffset)},
   {CC"getDeoptedLeafGraphIds",            CC"()[J",                                             FN_PTR(getDeoptedLeafGraphIds)},
 };