# HG changeset patch # User Doug Simon # Date 1334663558 -7200 # Node ID 8bf2c37c46c48c22208ab06ca18036855626e709 # Parent 71ac4221b1b008f431d5bd466d5dc27bad55b87c added RiCompiledMethod.executeVarargs(Object...) to support compiling and calling arbitrary Java methods diff -r 71ac4221b1b0 -r 8bf2c37c46c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- 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(); diff -r 71ac4221b1b0 -r 8bf2c37c46c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- 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 diff -r 71ac4221b1b0 -r 8bf2c37c46c4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotCompiledMethod.java --- 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); + } } diff -r 71ac4221b1b0 -r 8bf2c37c46c4 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java --- 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 diff -r 71ac4221b1b0 -r 8bf2c37c46c4 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiCompiledMethod.java --- 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); } diff -r 71ac4221b1b0 -r 8bf2c37c46c4 src/share/vm/graal/graalCompilerToVM.cpp --- 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)}, };