changeset 22121:d045a505c2b3

Asynchronous TruffleVM can be created by providing own Executor when configuring the TruffleVM.Builder
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 02 Sep 2015 10:44:54 +0200
parents fe5df1f36fec
children ac017ff52c07
files truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java
diffstat 6 files changed, 225 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java	Mon Aug 31 18:15:27 2015 -0700
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java	Wed Sep 02 10:44:54 2015 +0200
@@ -31,6 +31,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.concurrent.Executors;
 import static org.junit.Assert.*;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -47,12 +48,12 @@
 
     @Test
     public void canGetAccessToOwnLanguageInstance() throws Exception {
-        TruffleVM vm = TruffleVM.newVM().build();
+        TruffleVM vm = TruffleVM.newVM().executor(Executors.newSingleThreadExecutor()).build();
         TruffleVM.Language language = vm.getLanguages().get(L1);
         assertNotNull("L1 language is defined", language);
 
         Source s = Source.fromText("return nothing", "nothing").withMimeType(L1);
-        Object ret = vm.eval(s);
+        Object ret = vm.eval(s).get();
         assertNull("nothing is returned", ret);
 
         Object afterInitialization = findLanguageByClass(vm);
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java	Mon Aug 31 18:15:27 2015 -0700
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java	Wed Sep 02 10:44:54 2015 +0200
@@ -23,23 +23,21 @@
 package com.oracle.truffle.api.test.vm;
 
 import com.oracle.truffle.api.source.Source;
-import static org.junit.Assert.*;
-
-import java.io.*;
-
-import org.junit.*;
-
 import static com.oracle.truffle.api.test.vm.ImplicitExplicitExportTest.L3;
 import com.oracle.truffle.api.vm.*;
+import java.io.*;
+import java.util.concurrent.Executors;
+import org.junit.*;
+import static org.junit.Assert.*;
 
 public class GlobalSymbolTest {
     @Test
     public void globalSymbolFoundByLanguage() throws IOException {
-        TruffleVM vm = TruffleVM.newVM().globalSymbol("ahoj", "42").build();
+        TruffleVM vm = TruffleVM.newVM().globalSymbol("ahoj", "42").executor(Executors.newSingleThreadExecutor()).build();
         // @formatter:off
         Object ret = vm.eval(
             Source.fromText("return=ahoj", "Return").withMimeType(L3)
-        );
+        ).get();
         // @formatter:on
         assertEquals("42", ret);
     }
@@ -49,6 +47,6 @@
         TruffleVM vm = TruffleVM.newVM().globalSymbol("ahoj", "42").build();
         TruffleVM.Symbol ret = vm.findGlobalSymbol("ahoj");
         assertNotNull("Symbol found", ret);
-        assertEquals("42", ret.invoke(null));
+        assertEquals("42", ret.get());
     }
 }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Mon Aug 31 18:15:27 2015 -0700
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Wed Sep 02 10:44:54 2015 +0200
@@ -22,13 +22,6 @@
  */
 package com.oracle.truffle.api.test.vm;
 
-import static org.junit.Assert.*;
-
-import java.io.*;
-import java.util.*;
-
-import org.junit.*;
-
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.debug.*;
@@ -37,25 +30,37 @@
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.vm.*;
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.Executors;
+import org.junit.*;
+import static org.junit.Assert.*;
 
 public class ImplicitExplicitExportTest {
+    private static Thread mainThread;
     private TruffleVM vm;
 
     @Before
     public void initializeVM() {
-        vm = TruffleVM.newVM().build();
+        mainThread = Thread.currentThread();
+        vm = TruffleVM.newVM().executor(Executors.newSingleThreadExecutor()).build();
         assertTrue("Found " + L1 + " language", vm.getLanguages().containsKey(L1));
         assertTrue("Found " + L2 + " language", vm.getLanguages().containsKey(L2));
         assertTrue("Found " + L3 + " language", vm.getLanguages().containsKey(L3));
     }
 
+    @After
+    public void cleanThread() {
+        mainThread = null;
+    }
+
     @Test
     public void explicitExportFound() throws IOException {
         // @formatter:off
         vm.eval(Source.fromText("explicit.ahoj=42", "Fourty two").withMimeType(L1));
         Object ret = vm.eval(
             Source.fromText("return=ahoj", "Return").withMimeType(L3)
-        );
+        ).get();
         // @formatter:on
         assertEquals("42", ret);
     }
@@ -68,7 +73,7 @@
         );
         Object ret = vm.eval(
             Source.fromText("return=ahoj", "Return").withMimeType(L3)
-        );
+        ).get();
         // @formatter:on
         assertEquals("42", ret);
     }
@@ -84,10 +89,10 @@
         );
         Object ret = vm.eval(
             Source.fromText("return=ahoj", "Return").withMimeType(L3)
-        );
+        ).get();
         // @formatter:on
         assertEquals("Explicit import from L2 is used", "43", ret);
-        assertEquals("Global symbol is also 43", "43", vm.findGlobalSymbol("ahoj").invoke(null));
+        assertEquals("Global symbol is also 43", "43", vm.findGlobalSymbol("ahoj").get());
     }
 
     @Test
@@ -101,10 +106,10 @@
         );
         Object ret = vm.eval(
             Source.fromText("return=ahoj", "Return").withMimeType(L3)
-        );
+        ).get();
         // @formatter:on
         assertEquals("Explicit import from L2 is used", "43", ret);
-        assertEquals("Global symbol is also 43", "43", vm.findGlobalSymbol("ahoj").invoke(null));
+        assertEquals("Global symbol is also 43", "43", vm.findGlobalSymbol("ahoj").invoke(null).get());
     }
 
     private static final class Ctx {
@@ -121,6 +126,9 @@
 
         @Override
         protected Ctx createContext(Env env) {
+            if (mainThread != null) {
+                assertNotEquals("Should run asynchronously", Thread.currentThread(), mainThread);
+            }
             return new Ctx(env);
         }
 
@@ -164,6 +172,7 @@
         }
 
         private Object importExport(Source code) {
+            assertNotEquals("Should run asynchronously", Thread.currentThread(), mainThread);
             final Node node = createFindContextNode();
             Ctx ctx = findContext(node);
             Properties p = new Properties();
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java	Mon Aug 31 18:15:27 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java	Wed Sep 02 10:44:54 2015 +0200
@@ -24,12 +24,6 @@
  */
 package com.oracle.truffle.api.vm;
 
-import java.io.*;
-import java.net.*;
-import java.nio.file.*;
-import java.util.*;
-import java.util.logging.*;
-
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.TruffleLanguage.Registration;
@@ -37,6 +31,13 @@
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.source.*;
+import java.io.*;
+import java.net.*;
+import java.nio.file.*;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.logging.*;
 
 /**
  * <em>Virtual machine</em> for Truffle based languages. Term virtual machine is a bit overloaded,
@@ -75,6 +76,7 @@
     private static final Logger LOG = Logger.getLogger(TruffleVM.class.getName());
     private static final SPIAccessor SPI = new SPIAccessor();
     private final Thread initThread;
+    private final Executor executor;
     private final Map<String, Language> langs;
     private final Reader in;
     private final Writer err;
@@ -94,16 +96,14 @@
         this.langs = null;
         this.handlers = null;
         this.globals = null;
+        this.executor = null;
     }
 
     /**
      * Real constructor used from the builder.
-     *
-     * @param out stdout
-     * @param err stderr
-     * @param in stdin
      */
-    private TruffleVM(Map<String, Object> globals, Writer out, Writer err, Reader in, EventConsumer<?>[] handlers) {
+    private TruffleVM(Executor executor, Map<String, Object> globals, Writer out, Writer err, Reader in, EventConsumer<?>[] handlers) {
+        this.executor = executor;
         this.out = out;
         this.err = err;
         this.in = in;
@@ -194,6 +194,7 @@
         private Reader in;
         private final List<EventConsumer<?>> handlers = new ArrayList<>();
         private final Map<String, Object> globals = new HashMap<>();
+        private Executor executor;
 
         Builder() {
         }
@@ -253,7 +254,7 @@
          * and will take precedence over {@link TruffleLanguage#findExportedSymbol symbols exported
          * by languages itself}. Repeated use of <code>globalSymbol</code> is possible; later
          * definition of the same name overrides the previous one.
-         * 
+         *
          * @param name name of the symbol to register
          * @param obj value of the object - expected to be primitive wrapper, {@link String} or
          *            <code>TruffleObject</code> for mutual inter-operability
@@ -266,6 +267,26 @@
         }
 
         /**
+         * Provides own executor for running {@link TruffleVM} scripts. By default
+         * {@link TruffleVM#eval(com.oracle.truffle.api.source.Source)} and
+         * {@link Symbol#invoke(java.lang.Object, java.lang.Object...) are executed synchronously in
+         * the calling thread. Sometimes, however it is more beneficial to run them asynchronously -
+         * the easiest way to do so is to provide own executor when configuring the {
+         * @link #executor(java.util.concurrent.Executor) the builder}. The executor is expected to
+         * execute all {@link Runnable runnables} passed into its
+         * {@link Executor#execute(java.lang.Runnable)} method in the order they arrive and in a
+         * single (yet arbitrary) thread.
+         *
+         * @param executor the executor to use for internal execution inside the {@link #build() to
+         *            be created} {@link TruffleVM}
+         * @return instance of this builder
+         */
+        public Builder executor(Executor executor) {
+            this.executor = executor;
+            return this;
+        }
+
+        /**
          * Creates the {@link TruffleVM Truffle virtual machine}. The configuration is taken from
          * values passed into configuration methods in this class.
          *
@@ -281,7 +302,13 @@
             if (in == null) {
                 in = new InputStreamReader(System.in);
             }
-            return new TruffleVM(globals, out, err, in, handlers.toArray(new EventConsumer[0]));
+            Executor nonNullExecutor = executor != null ? executor : new Executor() {
+                @Override
+                public void execute(Runnable command) {
+                    command.run();
+                }
+            };
+            return new TruffleVM(nonNullExecutor, globals, out, err, in, handlers.toArray(new EventConsumer[0]));
         }
     }
 
@@ -307,7 +334,7 @@
      * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)}
      */
     @Deprecated
-    public Object eval(URI location) throws IOException {
+    public Symbol eval(URI location) throws IOException {
         checkThread();
         Source s;
         String mimeType;
@@ -329,7 +356,7 @@
             URLConnection conn = url.openConnection();
             mimeType = conn.getContentType();
         }
-        TruffleLanguage<?> l = getTruffleLang(mimeType);
+        Language l = langs.get(mimeType);
         if (l == null) {
             throw new IOException("No language for " + location + " with MIME type " + mimeType + " found. Supported types: " + langs.keySet());
         }
@@ -347,9 +374,9 @@
      * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)}
      */
     @Deprecated
-    public Object eval(String mimeType, Reader reader) throws IOException {
+    public Symbol eval(String mimeType, Reader reader) throws IOException {
         checkThread();
-        TruffleLanguage<?> l = getTruffleLang(mimeType);
+        Language l = langs.get(mimeType);
         if (l == null) {
             throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet());
         }
@@ -367,9 +394,9 @@
      * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)}
      */
     @Deprecated
-    public Object eval(String mimeType, String code) throws IOException {
+    public Symbol eval(String mimeType, String code) throws IOException {
         checkThread();
-        TruffleLanguage<?> l = getTruffleLang(mimeType);
+        Language l = langs.get(mimeType);
         if (l == null) {
             throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet());
         }
@@ -385,24 +412,44 @@
      * @return result of an execution, possibly <code>null</code>
      * @throws IOException thrown to signal errors while processing the code
      */
-    public Object eval(Source source) throws IOException {
+    public Symbol eval(Source source) throws IOException {
         String mimeType = source.getMimeType();
         checkThread();
-        TruffleLanguage<?> l = getTruffleLang(mimeType);
+        Language l = langs.get(mimeType);
         if (l == null) {
             throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet());
         }
         return eval(l, source);
     }
 
-    private Object eval(TruffleLanguage<?> l, Source s) throws IOException {
-        TruffleVM.findDebuggerSupport(l);
-        Debugger[] fillIn = {debugger};
+    private Symbol eval(final Language l, final Source s) throws IOException {
+        final Debugger[] fillIn = {debugger};
+        final Object[] result = {null, null};
+        final CountDownLatch ready = new CountDownLatch(1);
+        final TruffleLanguage[] lang = {null};
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                TruffleLanguage<?> langImpl = l.getImpl();
+                lang[0] = langImpl;
+                TruffleVM.findDebuggerSupport(langImpl);
+                evalImpl(fillIn, s, result, langImpl, ready);
+            }
+        });
+        exceptionCheck(result);
+        return new Symbol(lang[0], result, ready);
+    }
+
+    private void evalImpl(Debugger[] fillIn, Source s, Object[] result, TruffleLanguage<?> l, CountDownLatch ready) {
         try (Closeable d = SPI.executionStart(this, fillIn, s)) {
             if (debugger == null) {
                 debugger = fillIn[0];
             }
-            return SPI.eval(l, s);
+            result[0] = SPI.eval(l, s);
+        } catch (IOException ex) {
+            result[1] = ex;
+        } finally {
+            ready.countDown();
         }
     }
 
@@ -423,34 +470,51 @@
      * @param globalName the name of the symbol to find
      * @return found symbol or <code>null</code> if it has not been found
      */
-    public Symbol findGlobalSymbol(String globalName) {
+    public Symbol findGlobalSymbol(final String globalName) {
         checkThread();
-        TruffleLanguage<?> lang = null;
-        Object obj = globals.get(globalName);
-        Object global = null;
-        if (obj == null) {
+        final TruffleLanguage<?>[] lang = {null};
+        final Object[] obj = {globals.get(globalName), null};
+        final CountDownLatch ready = new CountDownLatch(1);
+        if (obj[0] == null) {
+            executor.execute(new Runnable() {
+                @Override
+                public void run() {
+                    findGlobalSymbolImpl(obj, globalName, lang, ready);
+                }
+            });
+            try {
+                ready.await();
+            } catch (InterruptedException ex) {
+                LOG.log(Level.SEVERE, null, ex);
+            }
+        } else {
+            ready.countDown();
+        }
+        return obj[0] == null ? null : new Symbol(lang[0], obj, ready);
+    }
+
+    private void findGlobalSymbolImpl(Object[] obj, String globalName, TruffleLanguage<?>[] lang, CountDownLatch ready) {
+        if (obj[0] == null) {
             for (Language dl : langs.values()) {
                 TruffleLanguage<?> l = dl.getImpl();
-                obj = SPI.findExportedSymbol(dl.env, globalName, true);
-                if (obj != null) {
-                    lang = l;
-                    global = SPI.languageGlobal(dl.env);
+                obj[0] = SPI.findExportedSymbol(dl.getEnv(), globalName, true);
+                if (obj[0] != null) {
+                    lang[0] = l;
                     break;
                 }
             }
         }
-        if (obj == null) {
+        if (obj[0] == null) {
             for (Language dl : langs.values()) {
                 TruffleLanguage<?> l = dl.getImpl();
-                obj = SPI.findExportedSymbol(dl.env, globalName, false);
-                if (obj != null) {
-                    lang = l;
-                    global = SPI.languageGlobal(dl.env);
+                obj[0] = SPI.findExportedSymbol(dl.getEnv(), globalName, false);
+                if (obj[0] != null) {
+                    lang[0] = l;
                     break;
                 }
             }
         }
-        return obj == null ? null : new Symbol(lang, obj, global);
+        ready.countDown();
     }
 
     private void checkThread() {
@@ -459,12 +523,6 @@
         }
     }
 
-    private TruffleLanguage<?> getTruffleLang(String mimeType) {
-        checkThread();
-        Language l = langs.get(mimeType);
-        return l == null ? null : l.getImpl();
-    }
-
     @SuppressWarnings("all")
     void dispatch(Object ev) {
         Class type = ev.getClass();
@@ -494,20 +552,44 @@
         }
     }
 
+    static void exceptionCheck(Object[] result) throws RuntimeException, IOException {
+        if (result[1] instanceof IOException) {
+            throw (IOException) result[1];
+        }
+        if (result[1] instanceof RuntimeException) {
+            throw (RuntimeException) result[1];
+        }
+    }
+
     /**
      * Represents {@link TruffleVM#findGlobalSymbol(java.lang.String) global symbol} provided by one
      * of the initialized languages in {@link TruffleVM Truffle virtual machine}.
      */
     public class Symbol {
         private final TruffleLanguage<?> language;
-        private final Object obj;
-        private final Object global;
+        private final Object[] result;
+        private final CountDownLatch ready;
         private CallTarget target;
 
-        Symbol(TruffleLanguage<?> language, Object obj, Object global) {
+        Symbol(TruffleLanguage<?> language, Object[] result, CountDownLatch ready) {
             this.language = language;
-            this.obj = obj;
-            this.global = global;
+            this.result = result;
+            this.ready = ready;
+        }
+
+        /**
+         * Obtains the object represented by this symbol. The <em>raw</em> object can either be a
+         * wrapper about primitive type (e.g. {@link Number}, {@link String}, {@link Character},
+         * {@link Boolean}) or a <em>TruffleObject</em> representing more complex object from a
+         * language. The method can return <code>null</code>.
+         *
+         * @return the object or <code>null</code>
+         * @throws IOException in case it is not possible to obtain the value of the object
+         */
+        public Object get() throws IOException {
+            waitForSymbol();
+            exceptionCheck(result);
+            return result[0];
         }
 
         /**
@@ -522,15 +604,29 @@
          * @return the value returned by invoking the symbol
          * @throws IOException signals problem during execution
          */
-        public Object invoke(Object thiz, Object... args) throws IOException {
-            checkThread();
-            Debugger[] fillIn = {debugger};
-            try (Closeable c = SPI.executionStart(TruffleVM.this, fillIn, null)) {
+        public Symbol invoke(final Object thiz, final Object... args) throws IOException {
+            get();
+            final Debugger[] fillIn = {debugger};
+            final CountDownLatch done = new CountDownLatch(1);
+            final Object[] res = {null, null};
+            executor.execute(new Runnable() {
+                @Override
+                public void run() {
+                    invokeImpl(fillIn, thiz, args, res, done);
+                }
+            });
+            exceptionCheck(res);
+            return new Symbol(language, res, done);
+        }
+
+        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) {
                     debugger = fillIn[0];
                 }
                 List<Object> arr = new ArrayList<>();
-                if (thiz == null) {
+                if (thiz == null && language != null) {
+                    Object global = SPI.languageGlobal(SPI.findLanguage(TruffleVM.this, language.getClass()));
                     if (global != null) {
                         arr.add(global);
                     }
@@ -539,15 +635,31 @@
                 }
                 arr.addAll(Arrays.asList(args));
                 for (;;) {
-                    if (target == null) {
-                        target = SPI.createCallTarget(language, obj, arr.toArray());
-                    }
                     try {
-                        return target.call(arr.toArray());
+                        if (target == null) {
+                            target = SPI.createCallTarget(language, result[0], arr.toArray());
+                        }
+                        res[0] = target.call(arr.toArray());
+                        break;
                     } catch (SymbolInvoker.ArgumentsMishmashException ex) {
                         target = null;
                     }
                 }
+            } catch (IOException ex) {
+                res[1] = ex;
+            } catch (RuntimeException ex) {
+                res[1] = ex;
+            } finally {
+                done.countDown();
+            }
+        }
+
+        private void waitForSymbol() throws InterruptedIOException {
+            checkThread();
+            try {
+                ready.await();
+            } catch (InterruptedException ex) {
+                throw (InterruptedIOException) new InterruptedIOException(ex.getMessage()).initCause(ex);
             }
         }
     }
@@ -637,6 +749,13 @@
         public String toString() {
             return "[" + getShortName() + " for " + getMimeTypes() + "]";
         }
+
+        TruffleLanguage.Env getEnv() {
+            if (env == null) {
+                env = SPI.attachEnv(TruffleVM.this, impl, out, err, in);
+            }
+            return env;
+        }
     } // end of Language
 
     //
@@ -658,7 +777,7 @@
         for (Map.Entry<String, Language> entrySet : langs.entrySet()) {
             Language languageDescription = entrySet.getValue();
             if (languageClazz.isInstance(languageDescription.impl)) {
-                return languageDescription.env;
+                return languageDescription.getEnv();
             }
         }
         throw new IllegalStateException("Cannot find language " + languageClazz + " among " + langs);
@@ -681,7 +800,7 @@
                 if (l == ownLang) {
                     continue;
                 }
-                Object obj = SPI.findExportedSymbol(dl.env, globalName, true);
+                Object obj = SPI.findExportedSymbol(dl.getEnv(), globalName, true);
                 if (obj != null) {
                     return obj;
                 }
@@ -691,7 +810,7 @@
                 if (l == ownLang) {
                     continue;
                 }
-                Object obj = SPI.findExportedSymbol(dl.env, globalName, false);
+                Object obj = SPI.findExportedSymbol(dl.getEnv(), globalName, false);
                 if (obj != null) {
                     return obj;
                 }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Mon Aug 31 18:15:27 2015 -0700
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Wed Sep 02 10:44:54 2015 +0200
@@ -245,7 +245,7 @@
 
         Source src = Source.fromFileName(path.toString());
         /* Parse the SL source file. */
-        Object result = context.eval(src.withMimeType("application/x-sl"));
+        Object result = context.eval(src.withMimeType("application/x-sl")).get();
         if (result != null) {
             out.println(result);
         }
@@ -270,7 +270,7 @@
                 long start = System.nanoTime();
                 /* Call the main entry point, without any arguments. */
                 try {
-                    result = main.invoke(null);
+                    result = main.invoke(null).get();
                     if (result != null) {
                         out.println(result);
                     }
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Mon Aug 31 18:15:27 2015 -0700
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Wed Sep 02 10:44:54 2015 +0200
@@ -139,7 +139,7 @@
     public void testFortyTwo() throws Exception {
         TruffleVM.Symbol fourtyTwo = findGlobalSymbol(fourtyTwo());
 
-        Object res = fourtyTwo.invoke(null);
+        Object res = fourtyTwo.invoke(null).get();
 
         assert res instanceof Number : "should yield a number, but was: " + res;
 
@@ -155,7 +155,7 @@
         }
         TruffleVM.Symbol retNull = findGlobalSymbol(returnsNull());
 
-        Object res = retNull.invoke(null);
+        Object res = retNull.invoke(null).get();
 
         assertNull("Should yield real Java null", res);
     }
@@ -168,7 +168,7 @@
 
         TruffleVM.Symbol plus = findGlobalSymbol(plusInt());
 
-        Object res = plus.invoke(null, a, b);
+        Object res = plus.invoke(null, a, b).get();
 
         assert res instanceof Number : "+ on two ints should yield a number, but was: " + res;
 
@@ -181,7 +181,7 @@
     public void testInvalidTestMethod() throws Exception {
         String mime = mimeType();
         String code = invalidCode();
-        Object ret = vm().eval(Source.fromText(code, "Invalid code").withMimeType(mime));
+        Object ret = vm().eval(Source.fromText(code, "Invalid code").withMimeType(mime)).get();
         fail("Should yield IOException, but returned " + ret);
     }
 
@@ -189,7 +189,7 @@
     public void testMaxOrMinValue() throws Exception {
         TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers());
 
-        Object res = apply.invoke(null, new MaxMinObject(true));
+        Object res = apply.invoke(null, new MaxMinObject(true)).get();
 
         assert res instanceof Number : "result should be a number: " + res;
 
@@ -202,7 +202,7 @@
     public void testMaxOrMinValue2() throws Exception {
         TruffleVM.Symbol apply = findGlobalSymbol(applyNumbers());
 
-        Object res = apply.invoke(null, new MaxMinObject(false));
+        Object res = apply.invoke(null, new MaxMinObject(false)).get();
 
         assert res instanceof Number : "result should be a number: " + res;
 
@@ -228,12 +228,12 @@
         for (int i = 0; i < 10; i++) {
             int quantum = r.nextInt(10);
             for (int j = 0; j < quantum; j++) {
-                Object res = count1.invoke(null);
+                Object res = count1.invoke(null).get();
                 assert res instanceof Number : "expecting number: " + res;
                 assert ((Number) res).intValue() == ++prev1 : "expecting " + prev1 + " but was " + res;
             }
             for (int j = 0; j < quantum; j++) {
-                Object res = count2.invoke(null);
+                Object res = count2.invoke(null).get();
                 assert res instanceof Number : "expecting number: " + res;
                 assert ((Number) res).intValue() == ++prev2 : "expecting " + prev2 + " but was " + res;
             }