Mercurial > hg > truffle
changeset 22141:46384e637592
Make sure the proper TruffleVM execution context is re-set before invoking an operation on a JavaInterop wrapper obtained via Symbol.as method.
author | Jaroslav Tulach <jaroslav.tulach@oracle.com> |
---|---|
date | Mon, 14 Sep 2015 11:02:52 +0200 |
parents | 92906003d607 |
children | cf604b9633c9 |
files | truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/JavaWrapper.java truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java |
diffstat | 4 files changed, 108 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/JavaWrapper.java Mon Sep 14 11:02:52 2015 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.vm; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +final class JavaWrapper implements InvocationHandler { + private final TruffleVM.Symbol value; + private final Object wrapper; + private final InvocationHandler chain; + + public JavaWrapper(TruffleVM.Symbol value, Object wrapper, InvocationHandler chain) { + this.value = value; + this.chain = chain; + this.wrapper = wrapper; + } + + static <T> T create(Class<T> representation, Object wrapper, TruffleVM.Symbol value) { + InvocationHandler chain = Proxy.getInvocationHandler(wrapper); + Object instance = Proxy.newProxyInstance(representation.getClassLoader(), new Class<?>[]{representation}, new JavaWrapper(value, wrapper, chain)); + return representation.cast(instance); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getDeclaringClass() == Object.class) { + return method.invoke(this, args); + } + TruffleVM.Symbol retValue = value.invokeProxy(chain, wrapper, method, args); + if (method.getReturnType() == void.class) { + return null; + } else { + Object realValue = retValue.get(); + if (realValue == null) { + return null; + } + if (Proxy.isProxyClass(realValue.getClass())) { + if (Proxy.getInvocationHandler(realValue) instanceof JavaWrapper) { + return realValue; + } + final Class<?> type = method.getReturnType(); + return create(type, realValue, retValue); + } + return realValue; + } + } + +}
--- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java Thu Sep 10 16:26:31 2015 +0200 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java Mon Sep 14 11:02:52 2015 +0200 @@ -34,6 +34,8 @@ import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.source.*; import java.io.*; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; import java.net.*; import java.nio.file.*; import java.util.*; @@ -586,7 +588,8 @@ if (representation.isInstance(obj)) { return representation.cast(obj); } - return JavaInterop.asJavaObject(representation, (TruffleObject) obj); + T wrapper = JavaInterop.asJavaObject(representation, (TruffleObject) obj); + return JavaWrapper.create(representation, wrapper, this); } /** @@ -618,6 +621,32 @@ } @SuppressWarnings("try") + final Symbol invokeProxy(final InvocationHandler chain, final Object wrapper, final Method method, final Object[] args) throws IOException { + final Debugger[] fillIn = {debugger}; + final CountDownLatch done = new CountDownLatch(1); + final Object[] res = {null, null}; + executor.execute(new Runnable() { + @Override + public void run() { + try (final Closeable c = SPI.executionStart(TruffleVM.this, fillIn, null)) { + if (debugger == null) { + debugger = fillIn[0]; + } + res[0] = chain.invoke(wrapper, method, args); + } catch (IOException ex) { + res[1] = ex; + } catch (Throwable ex) { + res[1] = ex; + } finally { + done.countDown(); + } + } + }); + exceptionCheck(res); + return new Symbol(language, res, done); + } + + @SuppressWarnings("try") private void invokeImpl(Debugger[] fillIn, Object thiz, Object[] args, Object[] res, CountDownLatch done) { try (final Closeable c = SPI.executionStart(TruffleVM.this, fillIn, null)) { if (debugger == null) {
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Thu Sep 10 16:26:31 2015 +0200 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Mon Sep 14 11:02:52 2015 +0200 @@ -75,6 +75,7 @@ @Override public Object execute(VirtualFrame frame) { + assert SLLanguage.INSTANCE.findContext0(SLLanguage.INSTANCE.createFindContextNode0()) != null; return bodyNode.executeGeneric(frame); }
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Thu Sep 10 16:26:31 2015 +0200 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Mon Sep 14 11:02:52 2015 +0200 @@ -583,10 +583,13 @@ } TruffleVM.Symbol s = vm().findGlobalSymbol(compoundObjectName); assert s != null : "Symbol " + compoundObjectName + " is not found!"; - CompoundObject obj = s.invoke(null).as(CompoundObject.class); + final TruffleVM.Symbol value = s.invoke(null); + CompoundObject obj = value.as(CompoundObject.class); + assertNotNull("Compound object for " + value + " found", obj); int traverse = RANDOM.nextInt(10); - while (traverse-- >= 0) { + for (int i = 1; i <= traverse; i++) { obj = obj.returnsThis(); + assertNotNull("Remains non-null even after " + i + " iteration", obj); } return obj; }