changeset 22314:e56d1a618f64

Need to send every invokeForeign into the executor
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Fri, 16 Oct 2015 18:28:21 +0200
parents 06c5171e44c8
children 518f8ead5d01
files truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ArrayTruffleObject.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineAsynchTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineTest.java truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java
diffstat 4 files changed, 74 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ArrayTruffleObject.java	Fri Oct 16 11:22:48 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ArrayTruffleObject.java	Fri Oct 16 18:28:21 2015 +0200
@@ -31,19 +31,26 @@
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.RootNode;
 import java.util.List;
+import static org.junit.Assert.assertNotEquals;
 
 final class ArrayTruffleObject implements TruffleObject, ForeignAccess.Factory10 {
     private final ForeignAccess access;
     private final Object[] values;
+    private final Thread forbiddenDupl;
 
     ArrayTruffleObject(Object[] values) {
-        this.access = ForeignAccess.create(getClass(), this);
+        this(values, null);
+    }
+
+    ArrayTruffleObject(Object[] values, Thread forbiddenDupl) {
+        this.access = forbiddenDupl == null ? ForeignAccess.create(getClass(), this) : null;
         this.values = values;
+        this.forbiddenDupl = forbiddenDupl;
     }
 
     @Override
     public ForeignAccess getForeignAccess() {
-        return access;
+        return access != null ? access : ForeignAccess.create(getClass(), this);
     }
 
     @Override
@@ -93,6 +100,9 @@
 
     @Override
     public CallTarget accessInvoke(int argumentsLength) {
+        if (argumentsLength == 1) {
+            return target(new DuplNode());
+        }
         if (argumentsLength == 2) {
             return target(new InvokeNode());
         }
@@ -148,4 +158,20 @@
             }
         }
     }
+
+    private final class DuplNode extends RootNode {
+        public DuplNode() {
+            super(TruffleLanguage.class, null, null);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            final List<Object> args = ForeignAccess.getArguments(frame);
+            if (!"dupl".equals(args.get(0))) {
+                return null;
+            }
+            assertNotEquals("Cannot allocate duplicate on forbidden thread", forbiddenDupl, Thread.currentThread());
+            return new ArrayTruffleObject(values);
+        }
+    }
 }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineAsynchTest.java	Fri Oct 16 11:22:48 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineAsynchTest.java	Fri Oct 16 18:28:21 2015 +0200
@@ -32,6 +32,11 @@
     }
 
     @Override
+    protected Thread forbiddenThread() {
+        return Thread.currentThread();
+    }
+
+    @Override
     protected PolyglotEngine.Builder createBuilder() {
         return PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor());
     }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineTest.java	Fri Oct 16 11:22:48 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineTest.java	Fri Oct 16 18:28:21 2015 +0200
@@ -47,7 +47,13 @@
         assertNotNull(res);
     }
 
+    protected Thread forbiddenThread() {
+        return null;
+    }
+
     private interface AccessArray {
+        AccessArray dupl();
+
         List<? extends Number> get(int index);
     }
 
@@ -55,10 +61,11 @@
     public void wrappedAsArray() throws Exception {
         Object[][] matrix = {{1, 2, 3}};
 
-        PolyglotEngine tvm = createBuilder().globalSymbol("arr", new ArrayTruffleObject(matrix)).build();
+        PolyglotEngine tvm = createBuilder().globalSymbol("arr", new ArrayTruffleObject(matrix, forbiddenThread())).build();
         PolyglotEngine.Language language1 = tvm.getLanguages().get("application/x-test-import-export-1");
         AccessArray access = language1.eval(Source.fromText("return=arr", "get the array")).as(AccessArray.class);
         assertNotNull("Array converted to list", access);
+        access = access.dupl();
         List<? extends Number> list = access.get(0);
         assertEquals("Size 3", 3, list.size());
         assertEquals(1, list.get(0));
--- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java	Fri Oct 16 11:22:48 2015 +0200
+++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java	Fri Oct 16 18:28:21 2015 +0200
@@ -51,6 +51,7 @@
 import java.util.logging.Logger;
 
 import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.TruffleLanguage.Registration;
@@ -65,6 +66,7 @@
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.Source;
 
 /**
@@ -525,14 +527,38 @@
 
     @SuppressWarnings("try")
     final Object invokeForeign(final Node foreignNode, final VirtualFrame frame, final TruffleObject receiver) throws IOException {
-        Object res;
-        try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) {
-            res = ForeignAccess.execute(foreignNode, frame, receiver, ForeignAccess.getArguments(frame).toArray());
+        final Object[] res = {null, null};
+        final CountDownLatch computed = new CountDownLatch(1);
+        final Thread caller = Thread.currentThread();
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) {
+                    final Object[] args = ForeignAccess.getArguments(frame).toArray();
+                    if (caller != Thread.currentThread()) {
+                        RootNode node = SymbolInvokerImpl.createTemporaryRoot(TruffleLanguage.class, foreignNode, receiver, args.length);
+                        final CallTarget target = Truffle.getRuntime().createCallTarget(node);
+                        res[0] = target.call(args);
+                    } else {
+                        res[0] = ForeignAccess.execute(foreignNode, frame, receiver, args);
+                    }
+                } catch (Exception ex) {
+                    res[1] = ex;
+                } finally {
+                    computed.countDown();
+                }
+            }
+        });
+        try {
+            computed.await();
+        } catch (InterruptedException ex) {
+            throw new InterruptedIOException(ex.getMessage());
         }
-        if (res instanceof TruffleObject) {
-            return new EngineTruffleObject(this, (TruffleObject) res);
+        exceptionCheck(res);
+        if (res[0] instanceof TruffleObject) {
+            return new EngineTruffleObject(this, (TruffleObject) res[0]);
         } else {
-            return res;
+            return res[0];
         }
     }
 
@@ -730,27 +756,7 @@
                 return representation.cast(obj);
             }
             if (JAVA_INTEROP_ENABLED) {
-                final Object[] ret = {null, null};
-                final CountDownLatch computed = new CountDownLatch(1);
-                executor.execute(new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            ret[0] = JavaInterop.asJavaObject(representation, (TruffleObject) obj);
-                        } catch (Exception ex) {
-                            ret[1] = ex;
-                        } finally {
-                            computed.countDown();
-                        }
-                    }
-                });
-                try {
-                    computed.await();
-                } catch (InterruptedException ex) {
-                    throw new InterruptedIOException(ex.getMessage());
-                }
-                exceptionCheck(ret);
-                return representation.cast(ret[0]);
+                return JavaInterop.asJavaObject(representation, (TruffleObject) obj);
             }
             throw new ClassCastException("Value cannot be represented as " + representation.getName());
         }