changeset 22452:163fdf64587d

Merge with a647534602a6b70deb64b9d96c2798d7e36e1e0e
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Wed, 11 Nov 2015 15:59:56 -0800
parents ad180d3d4bd7 (current diff) a647534602a6 (diff)
children 3edc03012975
files truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPL.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java
diffstat 90 files changed, 1501 insertions(+), 1263 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Nov 10 19:42:37 2015 -0800
+++ b/.hgtags	Wed Nov 11 15:59:56 2015 -0800
@@ -618,3 +618,4 @@
 
 7aab14a2bb4e5c06b2fb252753a4beca184eec5f graal-0.8
 7aab14a2bb4e5c06b2fb252753a4beca184eec5f truffle-0.8
+5ee16f4908e565c39fc6d8422fda53c677d350a7 truffle-0.9
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -42,6 +42,7 @@
 import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheFieldFactory;
 import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheMethodFactory;
 import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheNodeFieldFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCachesOrderFactory;
 import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithCachedAndDynamicParameterFactory;
 import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithJustCachedParameterFactory;
 import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestMultipleCachesFactory;
@@ -309,6 +310,35 @@
     }
 
     @NodeChild
+    static class TestCachesOrder extends ValueNode {
+
+        @Specialization(guards = "boundByGuard != 0")
+        static int do1(int value, //
+                        @Cached("get(value)") int intermediateValue, //
+                        @Cached("transform(intermediateValue)") int boundByGuard, //
+                        @Cached("new()") Object notBoundByGuards) {
+            return intermediateValue;
+        }
+
+        protected int get(int i) {
+            return i * 2;
+        }
+
+        protected int transform(int i) {
+            return i * 3;
+        }
+
+    }
+
+    @Test
+    public void testCachesOrder() {
+        CallTarget root = createCallTarget(TestCachesOrderFactory.getInstance());
+        assertEquals(42, root.call(21));
+        assertEquals(42, root.call(22));
+        assertEquals(42, root.call(23));
+    }
+
+    @NodeChild
     static class CachedError1 extends ValueNode {
         @Specialization
         static int do1(int value, @ExpectError("Incompatible return type int. The expression type must be equal to the parameter type double.")//
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -39,7 +39,7 @@
                     + "execute(VirtualFrame)' and must not throw any checked exceptions.";
 
     @TypeSystem({int.class})
-    @DSLOptions(useNewLayout = true)
+    @DSLOptions
     static class ExecuteMethodTypes {
     }
 
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -162,7 +162,7 @@
         static int fallthrough1;
         static int fallthrough2;
 
-        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        @Specialization(rewriteOn = ArithmeticException.class)
         int do1(int a) throws ArithmeticException {
             if (a == 0) {
                 fallthrough1++;
@@ -171,7 +171,7 @@
             return a;
         }
 
-        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        @Specialization(rewriteOn = ArithmeticException.class)
         int do2(int a) throws ArithmeticException {
             if (a == 1) {
                 fallthrough2++;
@@ -266,7 +266,7 @@
         static int fallthrough1;
         static int fallthrough2;
 
-        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        @Specialization(rewriteOn = ArithmeticException.class)
         int do1(int a) throws ArithmeticException {
             if (a == 0) {
                 fallthrough1++;
@@ -275,7 +275,7 @@
             return a;
         }
 
-        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        @Specialization(rewriteOn = ArithmeticException.class)
         int do2(int a) throws ArithmeticException {
             if (a == 1) {
                 fallthrough2++;
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -43,7 +43,7 @@
 
     @TypeSystem({byte.class, short.class, int.class, long.class, double.class, boolean.class, BigInteger.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class,
                     Abstract.class, Interface.class, Object[].class})
-    @DSLOptions(useNewLayout = true)
+    @DSLOptions
     static class SimpleTypes {
 
         static int intCheck;
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/utilities/InstrumentationTestMode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/utilities/InstrumentationTestMode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -34,7 +34,7 @@
     public static void set(boolean enable) {
 
         try {
-            final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+            final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
             final Field instrumenterField = vm.getClass().getDeclaredField("instrumenter");
             instrumenterField.setAccessible(true);
             final Object instrumenter = instrumenterField.get(vm);
--- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java	Tue Nov 10 19:42:37 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, 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.dsl;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Experimental API.
- *
- * @deprecated annotation has no effect anymore.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-@Deprecated
-public @interface Implies {
-
-    String[] value();
-
-}
--- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java	Tue Nov 10 19:42:37 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, 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.dsl;
-
-import com.oracle.truffle.api.Assumption;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * @deprecated use {@link NodeField} with type {@link Assumption} instead.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-@Deprecated
-public @interface NodeAssumptions {
-
-    String[] value();
-
-}
--- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java	Wed Nov 11 15:59:56 2015 -0800
@@ -119,18 +119,6 @@
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD})
 public @interface Specialization {
-
-    /**
-     * @deprecated do not use anymore. Will get removed in the next release.
-     */
-    @Deprecated int DEFAULT_ORDER = -1;
-
-    /**
-     * @deprecated use declaration order instead. Will get removed in the next release.
-     */
-    @Deprecated
-    int order() default DEFAULT_ORDER;
-
     /**
      * References a specialization of a super class by its method name where this specialization is
      * inserted before. The declaration order of a specialization is not usable for nodes where
--- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java	Wed Nov 11 15:59:56 2015 -0800
@@ -36,11 +36,6 @@
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.TYPE})
 public @interface DSLOptions {
-
-    /** Flag has no effect anymore. Is going to be removed soon. */
-    @Deprecated
-    boolean useNewLayout() default true;
-
     /**
      * Lazy class loading ensures that all generated specialization classes are loaded lazily.
      * Disabling this feature will eagerly load all classes but will also reduce the generated code
--- a/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/InstrumentationTestMode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/InstrumentationTestMode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -36,7 +36,7 @@
     public static void set(boolean enable) {
 
         try {
-            final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+            final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
             final Field instrumenterField = vm.getClass().getDeclaredField("instrumenter");
             instrumenterField.setAccessible(true);
             final Object instrumenter = instrumenterField.get(vm);
--- a/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/JavaFunctionTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/JavaFunctionTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -35,7 +35,7 @@
     public void invokeRunnable() throws IOException {
         final boolean[] called = {false};
 
-        PolyglotEngine engine = PolyglotEngine.buildNew().globalSymbol("test", JavaInterop.asTruffleFunction(Runnable.class, new Runnable() {
+        PolyglotEngine engine = PolyglotEngine.newBuilder().globalSymbol("test", JavaInterop.asTruffleFunction(Runnable.class, new Runnable() {
             @Override
             public void run() {
                 called[0] = true;
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -32,6 +32,8 @@
     @Child private ObjectAccessNode next;
     private final ForeignAccess languageCheck;
 
+    @Child private ForeignAccessArguments accessArguments = new ForeignAccessArguments();
+
     protected CachedObjectAccessNode(DirectCallNode callTarget, ObjectAccessNode next, ForeignAccess languageCheck) {
         this.callTarget = callTarget;
         this.next = next;
@@ -50,7 +52,7 @@
 
     private Object doAccess(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
         if (languageCheck.canHandle(receiver)) {
-            return callTarget.call(frame, ForeignAccessArguments.create(receiver, arguments));
+            return callTarget.call(frame, accessArguments.executeCreate(receiver, arguments));
         } else {
             return doNext(frame, receiver, arguments);
         }
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java	Wed Nov 11 15:59:56 2015 -0800
@@ -130,9 +130,7 @@
     }
 
     private void checkThread() {
-        if (initThread != Thread.currentThread()) {
-            throw new IllegalStateException("ForeignAccess created on " + initThread.getName() + " but used on " + Thread.currentThread().getName());
-        }
+        assert initThread == Thread.currentThread();
     }
 
     CallTarget access(Message message) {
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java	Wed Nov 11 15:59:56 2015 -0800
@@ -24,19 +24,41 @@
  */
 package com.oracle.truffle.api.interop;
 
-final class ForeignAccessArguments {
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.nodes.Node;
+
+final class ForeignAccessArguments extends Node {
+
     static final Object[] EMPTY_ARGUMENTS_ARRAY = new Object[0];
     static final int RECEIVER_INDEX = 0;
     static final int RUNTIME_ARGUMENT_COUNT = 1;
 
-    static Object[] create(Object receiver, Object... arguments) {
-        if (arguments.length == 0) {
-            return new Object[]{receiver};
+    @CompilationFinal private int previousLength = -2;
+
+    public Object[] executeCreate(Object receiver, Object... arguments) {
+        int length = profileLength(arguments.length);
+        Object[] objectArguments = new Object[RUNTIME_ARGUMENT_COUNT + length];
+        objectArguments[RECEIVER_INDEX] = receiver;
+        arraycopy(arguments, 0, objectArguments, RUNTIME_ARGUMENT_COUNT, length);
+        return objectArguments;
+    }
+
+    private int profileLength(int length) {
+        int returnLength = length;
+        if (previousLength != -1) {
+            if (previousLength == length) {
+                returnLength = previousLength;
+            } else {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (previousLength == -2) {
+                    previousLength = length;
+                } else {
+                    previousLength = -1;
+                }
+            }
         }
-        Object[] objectArguments = new Object[RUNTIME_ARGUMENT_COUNT + arguments.length];
-        objectArguments[RECEIVER_INDEX] = receiver;
-        arraycopy(arguments, 0, objectArguments, RUNTIME_ARGUMENT_COUNT, arguments.length);
-        return objectArguments;
+        return returnLength;
     }
 
     private static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GenericObjectAccessNode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GenericObjectAccessNode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -34,6 +34,8 @@
     private final Message access;
     @Child private IndirectCallNode indirectCallNode;
 
+    @Child private ForeignAccessArguments accessArguments = new ForeignAccessArguments();
+
     public GenericObjectAccessNode(Message access) {
         this.access = access;
         indirectCallNode = Truffle.getRuntime().createIndirectCallNode();
@@ -50,7 +52,7 @@
         if (ct == null) {
             throw messageNotRecognizedException(fa);
         }
-        return indirectCallNode.call(frame, ct, ForeignAccessArguments.create(truffleObject, arguments));
+        return indirectCallNode.call(frame, ct, accessArguments.executeCreate(truffleObject, arguments));
     }
 
     @CompilerDirectives.TruffleBoundary
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java	Wed Nov 11 15:59:56 2015 -0800
@@ -35,10 +35,6 @@
  * An object may change its shape but only to shapes of the same layout.
  */
 public abstract class Layout {
-    @Deprecated public static final EnumSet<ImplicitCast> NONE = EnumSet.noneOf(ImplicitCast.class);
-    @Deprecated public static final EnumSet<ImplicitCast> INT_TO_DOUBLE = EnumSet.of(ImplicitCast.IntToDouble);
-    @Deprecated public static final EnumSet<ImplicitCast> INT_TO_LONG = EnumSet.of(ImplicitCast.IntToLong);
-
     public static final String OPTION_PREFIX = "truffle.object.";
 
     private static final LayoutFactory LAYOUT_FACTORY = loadLayoutFactory();
@@ -65,15 +61,6 @@
         return newLayout().build();
     }
 
-    /**
-     * Equivalent to
-     * {@code Layout.newLayout().setAllowedImplicitCasts(allowedImplicitCasts).build()}.
-     */
-    @Deprecated
-    public static Layout createLayout(EnumSet<ImplicitCast> allowedImplicitCasts) {
-        return newLayout().setAllowedImplicitCasts(allowedImplicitCasts).build();
-    }
-
     public abstract DynamicObject newInstance(Shape shape);
 
     public abstract Class<? extends DynamicObject> getType();
@@ -134,6 +121,7 @@
      */
     public static final class Builder {
         private EnumSet<ImplicitCast> allowedImplicitCasts;
+        private boolean polymorphicUnboxing;
 
         /**
          * Create a new layout builder.
@@ -169,13 +157,20 @@
             return this;
         }
 
-        @Deprecated
-        public EnumSet<ImplicitCast> getAllowedImplicitCasts() {
-            return allowedImplicitCasts;
+        /**
+         * If {@code true}, try to keep properties with polymorphic primitive types unboxed.
+         */
+        public Builder setPolymorphicUnboxing(boolean polymorphicUnboxing) {
+            this.polymorphicUnboxing = polymorphicUnboxing;
+            return this;
         }
     }
 
     protected static EnumSet<ImplicitCast> getAllowedImplicitCasts(Builder builder) {
         return builder.allowedImplicitCasts;
     }
+
+    protected static boolean getPolymorphicUnboxing(Builder builder) {
+        return builder.polymorphicUnboxing;
+    }
 }
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java	Wed Nov 11 15:59:56 2015 -0800
@@ -65,6 +65,7 @@
         return null;
     }
 
+    @Deprecated
     public ForeignAccess getForeignAccessFactory() {
         return ForeignAccess.create(new com.oracle.truffle.api.interop.ForeignAccess.Factory() {
 
@@ -77,4 +78,13 @@
             }
         });
     }
+
+    /**
+     * Create a {@link ForeignAccess} to access a specific {@link DynamicObject}.
+     *
+     * @param object the object to be accessed
+     */
+    public ForeignAccess getForeignAccessFactory(DynamicObject object) {
+        return getForeignAccessFactory();
+    }
 }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -58,7 +58,7 @@
     public void before() {
         // TODO (mlvdv) eventually abstract this
         try {
-            vm = PolyglotEngine.buildNew().build();
+            vm = PolyglotEngine.newBuilder().build();
             final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
             field.setAccessible(true);
             instrumenter = (Instrumenter) field.get(vm);
@@ -99,7 +99,7 @@
         final Source source42 = InstrumentationTestingLanguage.createConstantSource42("testEvalInstrumentListener");
         final int[] evalResult = {0};
         final int[] evalCount = {0};
-        final Instrument instrument = instrumenter.attach(addNodeProbe[0], InstrumentationTestingLanguage.class, source42, new EvalInstrumentListener() {
+        final Instrument instrument = instrumenter.attach(addNodeProbe[0], source42, new EvalInstrumentListener() {
 
             public void onExecution(Node node, VirtualFrame vFrame, Object result) {
                 evalCount[0] = evalCount[0] + 1;
@@ -112,7 +112,7 @@
                 fail("Eval test evaluates without exception");
 
             }
-        }, "test EvalInstrument");
+        }, "test EvalInstrument", null);
 
         assertEquals(vm.eval(source13).get(), 13);
         assertEquals(evalCount[0], 1);
@@ -124,7 +124,7 @@
         assertEquals(evalResult[0], 42);
 
         // Add new eval instrument with no listener, no effect on third execution
-        instrumenter.attach(addNodeProbe[0], InstrumentationTestingLanguage.class, source42, null, "");
+        instrumenter.attach(addNodeProbe[0], source42, null, "", null);
         assertEquals(vm.eval(source13).get(), 13);
         assertEquals(evalCount[0], 3);
         assertEquals(evalResult[0], 42);
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -64,7 +64,7 @@
 
     @Test
     public void testProbing() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
@@ -106,7 +106,7 @@
     @Test
     public void testTagging() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
 
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
@@ -243,10 +243,9 @@
                     leaveCount++;
                 }
 
-                public void onReturnExceptional(Probe p, Exception exception) {
+                public void onReturnExceptional(Probe p, Throwable exception) {
                     leaveCount++;
                 }
-
             }, "Instrumentation Test Counter");
         }
 
@@ -296,10 +295,9 @@
                     leaveCount++;
                 }
 
-                public void onReturnExceptional(Probe p, Node node, VirtualFrame vFrame, Exception exception) {
+                public void onReturnExceptional(Probe p, Node node, VirtualFrame vFrame, Throwable exception) {
                     leaveCount++;
                 }
-
             }, "Instrumentation Test Counter");
         }
 
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/interop/ForeignAccessSingleThreadedTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/interop/ForeignAccessSingleThreadedTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -49,7 +49,7 @@
         t.join();
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test(expected = AssertionError.class)
     public void accessNodeFromWrongThread() {
         Node n = Message.IS_EXECUTABLE.createNode();
         Object ret = ForeignAccess.execute(n, null, this);
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/InstrumentationTestMode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/InstrumentationTestMode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -34,7 +34,7 @@
     public static void set(boolean enable) {
 
         try {
-            final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+            final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
             final Field instrumenterField = vm.getClass().getDeclaredField("instrumenter");
             instrumenterField.setAccessible(true);
             final Object instrumenter = instrumenterField.get(vm);
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -50,7 +50,7 @@
 
     @Test
     public void canGetAccessToOwnLanguageInstance() throws Exception {
-        PolyglotEngine vm = PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()).build();
+        PolyglotEngine vm = PolyglotEngine.newBuilder().executor(Executors.newSingleThreadExecutor()).build();
         PolyglotEngine.Language language = vm.getLanguages().get(L1);
         assertNotNull("L1 language is defined", language);
 
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineAsynchTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineAsynchTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -38,6 +38,6 @@
 
     @Override
     protected PolyglotEngine.Builder createBuilder() {
-        return PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor());
+        return PolyglotEngine.newBuilder().executor(Executors.newSingleThreadExecutor());
     }
 }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineSingleThreadedTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineSingleThreadedTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -24,10 +24,9 @@
 
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import java.io.File;
 import java.io.IOException;
 import java.io.StringReader;
-import java.net.URI;
-import java.net.URISyntaxException;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -36,7 +35,7 @@
 
     @Before
     public void initInDifferentThread() throws InterruptedException {
-        final PolyglotEngine.Builder b = PolyglotEngine.buildNew();
+        final PolyglotEngine.Builder b = PolyglotEngine.newBuilder();
         Thread t = new Thread("Initializer") {
             @Override
             public void run() {
@@ -47,23 +46,20 @@
         t.join();
     }
 
-    @SuppressWarnings("deprecation")
     @Test(expected = IllegalStateException.class)
-    public void evalURI() throws IOException, URISyntaxException {
-        tvm.eval(new URI("http://unknown.js"));
+    public void evalURI() throws IOException {
+        tvm.eval(Source.fromURL(new File(".").toURI().toURL(), "wrong.test"));
     }
 
-    @SuppressWarnings("deprecation")
     @Test(expected = IllegalStateException.class)
     public void evalString() throws IOException {
-        tvm.eval("text/javascript", "1 + 1");
+        tvm.eval(Source.fromText("1 + 1", "wrong.test").withMimeType("text/javascript"));
     }
 
-    @SuppressWarnings("deprecation")
     @Test(expected = IllegalStateException.class)
     public void evalReader() throws IOException {
         try (StringReader sr = new StringReader("1 + 1")) {
-            tvm.eval("text/javascript", sr);
+            tvm.eval(Source.fromReader(sr, "wrong.test").withMimeType("text/javascript"));
         }
     }
 
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -31,7 +31,7 @@
 
 public class EngineTest {
     protected PolyglotEngine.Builder createBuilder() {
-        return PolyglotEngine.buildNew();
+        return PolyglotEngine.newBuilder();
     }
 
     @Test
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -47,7 +47,7 @@
 
     @Test
     public void canGetAccessToOwnLanguageInstance() throws Exception {
-        PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         PolyglotEngine.Language language = vm.getLanguages().get(L1);
         assertNotNull("L1 language is defined", language);
 
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolAsynchTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolAsynchTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -35,6 +35,6 @@
 
     @Override
     protected PolyglotEngine.Builder createEngineBuilder() {
-        return PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor());
+        return PolyglotEngine.newBuilder().executor(Executors.newSingleThreadExecutor());
     }
 }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -74,7 +74,7 @@
     }
 
     protected PolyglotEngine.Builder createEngineBuilder() {
-        return PolyglotEngine.buildNew();
+        return PolyglotEngine.newBuilder();
     }
 
     @Test
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -60,7 +60,7 @@
     @Before
     public void initializeVM() {
         mainThread = Thread.currentThread();
-        vm = PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()).build();
+        vm = PolyglotEngine.newBuilder().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));
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -71,7 +71,7 @@
     @Test
     public void accessProbeForAbstractLanguage() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
         final Debugger[] arr = {null};
-        PolyglotEngine vm = PolyglotEngine.buildNew().onEvent(new EventConsumer<ExecutionEvent>(ExecutionEvent.class) {
+        PolyglotEngine vm = PolyglotEngine.newBuilder().onEvent(new EventConsumer<ExecutionEvent>(ExecutionEvent.class) {
             @Override
             protected void on(ExecutionEvent event) {
                 arr[0] = event.getDebugger();
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ToStringTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ToStringTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -30,7 +30,7 @@
 public class ToStringTest {
     @Test
     public void valueToStringValueWith1() throws Exception {
-        PolyglotEngine engine = PolyglotEngine.buildNew().build();
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
         PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1");
         PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2");
         language2.eval(Source.fromText("explicit.value=42", "define 42"));
@@ -43,7 +43,7 @@
 
     @Test
     public void valueToStringValueWith2() throws Exception {
-        PolyglotEngine engine = PolyglotEngine.buildNew().build();
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
         PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1");
         PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2");
         language1.eval(Source.fromText("explicit.value=42", "define 42"));
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ValueTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ValueTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -41,7 +41,7 @@
 
     @Test
     public void valueToStringValue() throws Exception {
-        PolyglotEngine engine = PolyglotEngine.buildNew().build();
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
         PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1");
         PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2");
         language2.eval(Source.fromText("explicit.value=42", "define 42"));
@@ -56,7 +56,7 @@
 
     @Test
     public void valueToStringException() throws Exception {
-        PolyglotEngine engine = PolyglotEngine.buildNew().build();
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
         PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1");
         PolyglotEngine.Value value = null;
         try {
@@ -72,7 +72,7 @@
 
     @Test
     public void valueToStringValueAsync() throws Exception {
-        PolyglotEngine engine = PolyglotEngine.buildNew().executor(this).build();
+        PolyglotEngine engine = PolyglotEngine.newBuilder().executor(this).build();
         PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1");
         PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2");
         language2.eval(Source.fromText("explicit.value=42", "define 42"));
@@ -96,7 +96,7 @@
 
     @Test
     public void valueToStringExceptionAsync() throws Exception {
-        PolyglotEngine engine = PolyglotEngine.buildNew().executor(this).build();
+        PolyglotEngine engine = PolyglotEngine.newBuilder().executor(this).build();
         PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1");
         PolyglotEngine.Value value = language1.eval(Source.fromText("parse=does not work", "error.value"));
         assertNotNull("Value returned", value);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.vm/src/META-INF/upgrade/PolyglotEngineNewBuilder.hint	Wed Nov 11 15:59:56 2015 -0800
@@ -0,0 +1,6 @@
+'PolyglotEngine.buildNew() is misleading':
+com.oracle.truffle.api.vm.PolyglotEngine.buildNew()
+=>
+'Use newBuilder()':
+com.oracle.truffle.api.vm.PolyglotEngine.newBuilder()
+;;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/ComputeInExecutor.java	Wed Nov 11 15:59:56 2015 -0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014, 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.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.concurrent.Executor;
+
+abstract class ComputeInExecutor<R> implements Runnable {
+    private final Executor executor;
+    private R result;
+    private Throwable exception;
+    private boolean started;
+    private boolean done;
+
+    protected ComputeInExecutor(Executor executor) {
+        this.executor = executor;
+    }
+
+    protected abstract R compute() throws IOException;
+
+    public final R get() throws IOException {
+        perform();
+        if (executor != null) {
+            waitForDone();
+        }
+        exceptionCheck();
+        return result;
+    }
+
+    private void waitForDone() throws InterruptedIOException {
+        synchronized (this) {
+            while (!done) {
+                try {
+                    wait();
+                } catch (InterruptedException ex) {
+                    throw new InterruptedIOException(ex.getMessage());
+                }
+            }
+        }
+    }
+
+    private void exceptionCheck() throws IOException, RuntimeException {
+        if (exception instanceof IOException) {
+            throw (IOException) exception;
+        }
+        if (exception instanceof RuntimeException) {
+            throw (RuntimeException) exception;
+        }
+        if (exception != null) {
+            throw new RuntimeException(exception);
+        }
+    }
+
+    public final void perform() throws IOException {
+        if (started) {
+            return;
+        }
+        started = true;
+        if (executor == null) {
+            run();
+        } else {
+            executor.execute(this);
+        }
+        exceptionCheck();
+    }
+
+    @Override
+    public final void run() {
+        try {
+            result = compute();
+        } catch (Exception ex) {
+            exception = ex;
+        } finally {
+            if (executor != null) {
+                synchronized (this) {
+                    done = true;
+                    notifyAll();
+                }
+            } else {
+                done = true;
+            }
+        }
+    }
+
+    @Override
+    public final String toString() {
+        return "value=" + result + ",exception=" + exception + ",computed=" + done;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/IncompleteSourceException.java	Wed Nov 11 15:59:56 2015 -0800
@@ -0,0 +1,19 @@
+package com.oracle.truffle.api.vm;
+
+import java.io.IOException;
+
+/**
+ * Indicates that the provided source was incomplete and requires further text to be executed.
+ */
+@SuppressWarnings("serial")
+public class IncompleteSourceException extends IOException {
+
+    public IncompleteSourceException() {
+        super();
+    }
+
+    public IncompleteSourceException(Throwable cause) {
+        super(cause);
+    }
+
+}
--- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/LanguageCache.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/LanguageCache.java	Wed Nov 11 15:59:56 2015 -0800
@@ -25,6 +25,7 @@
 package com.oracle.truffle.api.vm;
 
 import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.TruffleOptions;
 import static com.oracle.truffle.api.vm.PolyglotEngine.LOG;
 import java.io.IOException;
 import java.io.InputStream;
@@ -39,8 +40,8 @@
 import java.util.logging.Level;
 
 /**
- * Ahead-of-time initialization. If the JVM is started with -Dcom.oracle.truffle.aot=true, it
- * populates cache with languages found in application classloader.
+ * Ahead-of-time initialization. If the JVM is started with {@link TruffleOptions#AOT}, it populates
+ * cache with languages found in application classloader.
  */
 final class LanguageCache {
     static final boolean PRELOAD;
@@ -53,7 +54,7 @@
 
     static {
         Map<String, LanguageCache> map = null;
-        if (Boolean.getBoolean("com.oracle.truffle.aot")) { // NOI18N
+        if (TruffleOptions.AOT) {
             map = languages();
             for (LanguageCache info : map.values()) {
                 info.getImpl(true);
--- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java	Wed Nov 11 15:59:56 2015 -0800
@@ -25,17 +25,9 @@
 package com.oracle.truffle.api.vm;
 
 import java.io.Closeable;
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InterruptedIOException;
 import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.net.URI;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -45,25 +37,25 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 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;
+import com.oracle.truffle.api.TruffleOptions;
 import com.oracle.truffle.api.debug.Debugger;
 import com.oracle.truffle.api.debug.ExecutionEvent;
 import com.oracle.truffle.api.debug.SuspendedEvent;
+import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.impl.Accessor;
 import com.oracle.truffle.api.instrument.Instrumenter;
-import com.oracle.truffle.api.instrument.KillException;
 import com.oracle.truffle.api.instrument.Probe;
-import com.oracle.truffle.api.instrument.QuitException;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
@@ -94,11 +86,12 @@
  * Use {@link #buildNew()} multiple times to create different, isolated portal environment
  * completely separated from each other.
  * <p>
- * Once instantiated use {@link #eval(java.net.URI)} with a reference to a file or URL or directly
- * pass code snippet into the virtual machine via {@link #eval(java.lang.String, java.lang.String)}.
- * Support for individual languages is initialized on demand - e.g. once a file of certain MIME type
- * is about to be processed, its appropriate engine (if found), is initialized. Once an engine gets
- * initialized, it remains so, until the virtual machine isn't garbage collected.
+ * Once instantiated use {@link #eval(com.oracle.truffle.api.source.Source)} with a reference to a
+ * file or URL or directly pass code snippet into the virtual machine via
+ * {@link #eval(com.oracle.truffle.api.source.Source)}. Support for individual languages is
+ * initialized on demand - e.g. once a file of certain MIME type is about to be processed, its
+ * appropriate engine (if found), is initialized. Once an engine gets initialized, it remains so,
+ * until the virtual machine isn't garbage collected.
  * <p>
  * The engine is single-threaded and tries to enforce that. It records the thread it has been
  * {@link Builder#build() created} by and checks that all subsequent calls are coming from the same
@@ -107,8 +100,7 @@
  */
 @SuppressWarnings("rawtypes")
 public class PolyglotEngine {
-    static final boolean JAVA_INTEROP_ENABLED = !Boolean.getBoolean("com.oracle.truffle.aot");
-
+    static final boolean JAVA_INTEROP_ENABLED = !TruffleOptions.AOT;
     static final Logger LOG = Logger.getLogger(PolyglotEngine.class.getName());
     private static final SPIAccessor SPI = new SPIAccessor();
     private final Thread initThread;
@@ -178,11 +170,11 @@
      *
      * It searches for {@link Registration languages registered} in the system class loader and
      * makes them available for later evaluation via
-     * {@link #eval(java.lang.String, java.lang.String)} methods.
+     * {@link #eval(com.oracle.truffle.api.source.Source)} method.
      *
-     * @return new, isolated virtual machine with pre-registered languages
+     * @return new builder to create isolated polyglot engine with pre-registered languages
      */
-    public static PolyglotEngine.Builder buildNew() {
+    public static PolyglotEngine.Builder newBuilder() {
         // making Builder non-static inner class is a
         // nasty trick to avoid the Builder class to appear
         // in Javadoc next to PolyglotEngine class
@@ -191,6 +183,15 @@
     }
 
     /**
+     * @return new builder
+     * @deprecated use {@link #newBuilder()}
+     */
+    @Deprecated
+    public static PolyglotEngine.Builder buildNew() {
+        return newBuilder();
+    }
+
+    /**
      * Builder for a new {@link PolyglotEngine}. Call various configuration methods in a chain and
      * at the end create new {@link PolyglotEngine virtual machine}:
      *
@@ -226,15 +227,6 @@
         }
 
         /**
-         * @deprecated does nothing
-         */
-        @Deprecated
-        @SuppressWarnings("unused")
-        public Builder stdOut(Writer w) {
-            return this;
-        }
-
-        /**
          * Changes the error output for languages running in <em>to be created</em>
          * {@link PolyglotEngine virtual machine}. The default is to use {@link System#err}.
          *
@@ -247,15 +239,6 @@
         }
 
         /**
-         * @deprecated does nothing
-         */
-        @Deprecated
-        @SuppressWarnings("unused")
-        public Builder stdErr(Writer w) {
-            return this;
-        }
-
-        /**
          * Changes the default input for languages running in <em>to be created</em>
          * {@link PolyglotEngine virtual machine}. The default is to use {@link System#in}.
          *
@@ -268,15 +251,6 @@
         }
 
         /**
-         * @deprecated does nothing
-         */
-        @Deprecated
-        @SuppressWarnings("unused")
-        public Builder stdIn(Reader r) {
-            return this;
-        }
-
-        /**
          * Registers another instance of {@link EventConsumer} into the to be created
          * {@link PolyglotEngine}.
          *
@@ -299,16 +273,24 @@
          *
          * @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
+         *            <code>TruffleObject</code> for mutual inter-operability. If the object isn't
+         *            of the previous types, the system tries to wrap it using
+         *            {@link JavaInterop#asTruffleObject(java.lang.Object)}, if available
          * @return instance of this builder
          * @see PolyglotEngine#findGlobalSymbol(java.lang.String)
+         * @throws IllegalArgumentException if the object isn't of primitive type and cannot be
+         *             converted to {@link TruffleObject}
          */
         public Builder globalSymbol(String name, Object obj) {
             final Object truffleReady;
-            if (obj instanceof Number || obj instanceof String || obj instanceof Character || obj instanceof Boolean) {
+            if (obj instanceof TruffleObject || obj instanceof Number || obj instanceof String || obj instanceof Character || obj instanceof Boolean) {
                 truffleReady = obj;
             } else {
-                truffleReady = JavaInterop.asTruffleObject(obj);
+                if (JAVA_INTEROP_ENABLED) {
+                    truffleReady = JavaInterop.asTruffleObject(obj);
+                } else {
+                    throw new IllegalArgumentException();
+                }
             }
             globals.put(name, truffleReady);
             return this;
@@ -351,13 +333,7 @@
             if (in == null) {
                 in = System.in;
             }
-            Executor nonNullExecutor = executor != null ? executor : new Executor() {
-                @Override
-                public void execute(Runnable command) {
-                    command.run();
-                }
-            };
-            return new PolyglotEngine(nonNullExecutor, globals, out, err, in, handlers.toArray(new EventConsumer[0]));
+            return new PolyglotEngine(executor, globals, out, err, in, handlers.toArray(new EventConsumer[0]));
         }
     }
 
@@ -372,79 +348,6 @@
     }
 
     /**
-     * Evaluates file located on a given URL. Is equivalent to loading the content of a file and
-     * executing it via {@link #eval(java.lang.String, java.lang.String)} with a MIME type guess
-     * based on the file's extension and/or content.
-     *
-     * @param location the location of a file to execute
-     * @return result of a processing the file, possibly <code>null</code>
-     * @throws IOException exception to signal I/O problems or problems with processing the file's
-     *             content
-     * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)}
-     */
-    @Deprecated
-    public Object eval(URI location) throws IOException {
-        checkThread();
-        Source s;
-        String mimeType;
-        if (location.getScheme().equals("file")) {
-            File file = new File(location);
-            s = Source.fromFileName(file.getPath(), true);
-            mimeType = Files.probeContentType(file.toPath());
-        } else {
-            URL url = location.toURL();
-            s = Source.fromURL(url, location.toString());
-            URLConnection conn = url.openConnection();
-            mimeType = conn.getContentType();
-        }
-        Language l = langs.get(mimeType);
-        if (l == null) {
-            throw new IOException("No language for " + location + " with MIME type " + mimeType + " found. Supported types: " + langs.keySet());
-        }
-        return eval(l, s).get();
-    }
-
-    /**
-     * Evaluates code snippet. Chooses a language registered for a given MIME type (throws
-     * {@link IOException} if there is none). And passes the specified code to it for execution.
-     *
-     * @param mimeType MIME type of the code snippet - chooses the right language
-     * @param reader the source of code snippet to execute
-     * @return result of an execution, possibly <code>null</code>
-     * @throws IOException thrown to signal errors while processing the code
-     * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)}
-     */
-    @Deprecated
-    public Object eval(String mimeType, Reader reader) throws IOException {
-        checkThread();
-        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.fromReader(reader, mimeType)).get();
-    }
-
-    /**
-     * Evaluates code snippet. Chooses a language registered for a given MIME type (throws
-     * {@link IOException} if there is none). And passes the specified code to it for execution.
-     *
-     * @param mimeType MIME type of the code snippet - chooses the right language
-     * @param code the code snippet to execute
-     * @return result of an execution, possibly <code>null</code>
-     * @throws IOException thrown to signal errors while processing the code
-     * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)}
-     */
-    @Deprecated
-    public Object eval(String mimeType, String code) throws IOException {
-        checkThread();
-        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.fromText(code, mimeType)).get();
-    }
-
-    /**
      * Evaluates provided source. Chooses language registered for a particular
      * {@link Source#getMimeType() MIME type} (throws {@link IOException} if there is none). The
      * language is then allowed to parse and execute the source.
@@ -475,9 +378,9 @@
     public void dispose() {
         checkThread();
         disposed = true;
-        executor.execute(new Runnable() {
+        ComputeInExecutor<Void> compute = new ComputeInExecutor<Void>(executor) {
             @Override
-            public void run() {
+            protected Void compute() throws IOException {
                 for (Language language : getLanguages().values()) {
                     TruffleLanguage<?> impl = language.getImpl(false);
                     if (impl != null) {
@@ -488,26 +391,26 @@
                         }
                     }
                 }
+                return null;
             }
-        });
+        };
+        try {
+            compute.perform();
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
     }
 
     private Value eval(final Language l, final Source s) throws IOException {
-        final Object[] result = {null, null};
-        final CountDownLatch ready = new CountDownLatch(1);
         final TruffleLanguage[] lang = {null};
-        executor.execute(new Runnable() {
+        ComputeInExecutor<Object> compute = new ComputeInExecutor<Object>(executor) {
             @Override
-            public void run() {
-                evalImpl(lang, s, result, l, ready);
+            protected Object compute() throws IOException {
+                return evalImpl(lang, s, l);
             }
-        });
-        exceptionCheck(result);
-        return createValue(lang, result, ready);
-    }
-
-    Value createValue(TruffleLanguage[] lang, Object[] result, CountDownLatch ready) {
-        return new Value(lang, result, ready);
+        };
+        compute.perform();
+        return new Value(lang, compute);
     }
 
     Language createLanguage(Map.Entry<String, LanguageCache> en) {
@@ -515,58 +418,53 @@
     }
 
     @SuppressWarnings("try")
-    private void evalImpl(TruffleLanguage<?>[] fillLang, Source s, Object[] result, Language l, CountDownLatch ready) {
+    private Object evalImpl(TruffleLanguage<?>[] fillLang, Source s, Language l) throws IOException {
         try (Closeable d = SPI.executionStart(this, -1, debugger, s)) {
             TruffleLanguage<?> langImpl = l.getImpl(true);
             fillLang[0] = langImpl;
-            result[0] = SPI.eval(langImpl, s);
-        } catch (IOException ex) {
-            result[1] = ex;
-        } finally {
-            ready.countDown();
+            return SPI.eval(langImpl, s);
         }
     }
 
     @SuppressWarnings("try")
-    final Object invokeForeign(final Node foreignNode, final VirtualFrame frame, final TruffleObject receiver) throws IOException {
-        final Object[] res = {null, null};
-        final CountDownLatch computed = new CountDownLatch(1);
-        final Thread caller = Thread.currentThread();
-        executor.execute(new Runnable() {
+    final Object invokeForeign(final Node foreignNode, VirtualFrame frame, final TruffleObject receiver) throws IOException {
+        Object res;
+        if (executor == null) {
+            try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) {
+                final Object[] args = ForeignAccess.getArguments(frame).toArray();
+                res = ForeignAccess.execute(foreignNode, frame, receiver, args);
+            }
+        } else {
+            res = invokeForeignOnExecutor(foreignNode, frame, receiver);
+        }
+        if (res instanceof TruffleObject) {
+            return new EngineTruffleObject(this, (TruffleObject) res);
+        } else {
+            return res;
+        }
+    }
+
+    @TruffleBoundary
+    private Object invokeForeignOnExecutor(final Node foreignNode, VirtualFrame frame, final TruffleObject receiver) throws IOException {
+        final MaterializedFrame materialized = frame.materialize();
+        ComputeInExecutor<Object> compute = new ComputeInExecutor<Object>(executor) {
+            @SuppressWarnings("try")
             @Override
-            public void run() {
+            protected Object compute() throws IOException {
                 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();
+                    final Object[] args = ForeignAccess.getArguments(materialized).toArray();
+                    RootNode node = SymbolInvokerImpl.createTemporaryRoot(TruffleLanguage.class, foreignNode, receiver, args.length);
+                    final CallTarget target = Truffle.getRuntime().createCallTarget(node);
+                    return target.call(args);
                 }
             }
-        });
-        try {
-            computed.await();
-        } catch (InterruptedException ex) {
-            throw new InterruptedIOException(ex.getMessage());
-        }
-        exceptionCheck(res);
-        if (res[0] instanceof TruffleObject) {
-            return new EngineTruffleObject(this, (TruffleObject) res[0]);
-        } else {
-            return res[0];
-        }
+        };
+        return compute.get();
     }
 
     /**
      * Looks global symbol provided by one of initialized languages up. First of all execute your
-     * program via one of your {@link #eval(java.lang.String, java.lang.String)} and then look
+     * program via one of your {@link #eval(com.oracle.truffle.api.source.Source)} and then look
      * expected symbol up using this method.
      * <p>
      * The names of the symbols are language dependent, but for example the Java language bindings
@@ -584,54 +482,48 @@
     public Value findGlobalSymbol(final String globalName) {
         checkThread();
         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);
+        ComputeInExecutor<Object> compute = new ComputeInExecutor<Object>(executor) {
+            @Override
+            protected Object compute() throws IOException {
+                Object obj = globals.get(globalName);
+                if (obj == null) {
+                    for (Language dl : langs.values()) {
+                        TruffleLanguage.Env env = dl.getEnv(false);
+                        if (env == null) {
+                            continue;
+                        }
+                        obj = SPI.findExportedSymbol(env, globalName, true);
+                        if (obj != null) {
+                            lang[0] = dl.getImpl(true);
+                            break;
+                        }
+                    }
                 }
-            });
-            try {
-                ready.await();
-            } catch (InterruptedException ex) {
-                LOG.log(Level.SEVERE, null, ex);
+                if (obj == null) {
+                    for (Language dl : langs.values()) {
+                        TruffleLanguage.Env env = dl.getEnv(false);
+                        if (env == null) {
+                            continue;
+                        }
+                        obj = SPI.findExportedSymbol(env, globalName, true);
+                        if (obj != null) {
+                            lang[0] = dl.getImpl(true);
+                            break;
+                        }
+                    }
+                }
+                return obj;
             }
-        } else {
-            ready.countDown();
+        };
+        try {
+            compute.perform();
+            if (compute.get() == null) {
+                return null;
+            }
+        } catch (IOException ex) {
+            // OK, go on
         }
-        return obj[0] == null ? null : createValue(lang, obj, ready);
-    }
-
-    private void findGlobalSymbolImpl(Object[] obj, String globalName, TruffleLanguage<?>[] lang, CountDownLatch ready) {
-        if (obj[0] == null) {
-            for (Language dl : langs.values()) {
-                TruffleLanguage.Env env = dl.getEnv(false);
-                if (env == null) {
-                    continue;
-                }
-                obj[0] = SPI.findExportedSymbol(env, globalName, true);
-                if (obj[0] != null) {
-                    lang[0] = dl.getImpl(true);
-                    break;
-                }
-            }
-        }
-        if (obj[0] == null) {
-            for (Language dl : langs.values()) {
-                TruffleLanguage.Env env = dl.getEnv(false);
-                if (env == null) {
-                    continue;
-                }
-                obj[0] = SPI.findExportedSymbol(env, globalName, true);
-                if (obj[0] != null) {
-                    lang[0] = dl.getImpl(true);
-                    break;
-                }
-            }
-        }
-        ready.countDown();
+        return new Value(lang, compute);
     }
 
     private void checkThread() {
@@ -672,15 +564,6 @@
         }
     }
 
-    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];
-        }
-    }
-
     /**
      * A future value wrapper. A user level wrapper around values returned by evaluation of various
      * {@link PolyglotEngine} functions like
@@ -694,14 +577,22 @@
      */
     public class Value {
         private final TruffleLanguage<?>[] language;
-        private final Object[] result;
-        private final CountDownLatch ready;
+        private final ComputeInExecutor<Object> compute;
         private CallTarget target;
 
-        Value(TruffleLanguage<?>[] language, Object[] result, CountDownLatch ready) {
+        Value(TruffleLanguage<?>[] language, ComputeInExecutor<Object> compute) {
+            this.language = language;
+            this.compute = compute;
+        }
+
+        Value(TruffleLanguage<?>[] language, final Object value) {
             this.language = language;
-            this.result = result;
-            this.ready = ready;
+            this.compute = new ComputeInExecutor<Object>(null) {
+                @Override
+                protected Object compute() throws IOException {
+                    return value;
+                }
+            };
         }
 
         /**
@@ -714,12 +605,11 @@
          * @throws IOException in case it is not possible to obtain the value of the object
          */
         public Object get() throws IOException {
-            waitForSymbol();
-            exceptionCheck(result);
-            if (result[0] instanceof TruffleObject) {
-                return new EngineTruffleObject(PolyglotEngine.this, (TruffleObject) result[0]);
+            Object result = waitForSymbol();
+            if (result instanceof TruffleObject) {
+                return new EngineTruffleObject(PolyglotEngine.this, (TruffleObject) result);
             } else {
-                return result[0];
+                return result;
             }
         }
 
@@ -778,69 +668,48 @@
          */
         public Value invoke(final Object thiz, final Object... args) throws IOException {
             get();
-            final CountDownLatch done = new CountDownLatch(1);
-            final Object[] res = {null, null};
-            executor.execute(new Runnable() {
+            ComputeInExecutor<Object> invokeCompute = new ComputeInExecutor<Object>(executor) {
+                @SuppressWarnings("try")
                 @Override
-                public void run() {
-                    invokeImpl(thiz, args, res, done);
-                }
-            });
-            exceptionCheck(res);
-            return createValue(language, res, done);
-        }
-
-        @SuppressWarnings("try")
-        private void invokeImpl(Object thiz, Object[] args, Object[] res, CountDownLatch done) {
-            try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) {
-                List<Object> arr = new ArrayList<>();
-                if (thiz == null) {
-                    if (language[0] != null) {
-                        Object global = SPI.languageGlobal(SPI.findLanguage(PolyglotEngine.this, language[0].getClass()));
-                        if (global != null) {
-                            arr.add(global);
+                protected Object compute() throws IOException {
+                    try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) {
+                        List<Object> arr = new ArrayList<>();
+                        if (thiz == null) {
+                            if (language[0] != null) {
+                                Object global = SPI.languageGlobal(SPI.findLanguage(PolyglotEngine.this, language[0].getClass()));
+                                if (global != null) {
+                                    arr.add(global);
+                                }
+                            }
+                        } else {
+                            arr.add(thiz);
+                        }
+                        arr.addAll(Arrays.asList(args));
+                        for (;;) {
+                            try {
+                                if (target == null) {
+                                    target = SymbolInvokerImpl.createCallTarget(language[0], compute.get(), arr.toArray());
+                                }
+                                return target.call(arr.toArray());
+                            } catch (ArgumentsMishmashException ex) {
+                                target = null;
+                            }
                         }
                     }
-                } else {
-                    arr.add(thiz);
                 }
-                arr.addAll(Arrays.asList(args));
-                for (;;) {
-                    try {
-                        if (target == null) {
-                            target = SymbolInvokerImpl.createCallTarget(language[0], result[0], arr.toArray());
-                        }
-                        res[0] = target.call(arr.toArray());
-                        break;
-                    } catch (ArgumentsMishmashException ex) {
-                        target = null;
-                    }
-                }
-            } catch (KillException | QuitException ex) {
-                throw ex;
-            } catch (IOException ex) {
-                res[1] = ex;
-            } catch (RuntimeException ex) {
-                res[1] = ex;
-            } finally {
-                done.countDown();
-            }
+            };
+            invokeCompute.perform();
+            return new Value(language, invokeCompute);
         }
 
-        private void waitForSymbol() throws InterruptedIOException {
+        private Object waitForSymbol() throws IOException {
             checkThread();
-            try {
-                if (ready != null) {
-                    ready.await();
-                }
-            } catch (InterruptedException ex) {
-                throw (InterruptedIOException) new InterruptedIOException(ex.getMessage()).initCause(ex);
-            }
+            return compute.get();
         }
 
         @Override
         public String toString() {
-            return "PolyglotEngine.Value[value=" + result[0] + ",exception=" + result[1] + ",computed=" + (ready.getCount() == 0) + "]";
+            return "PolyglotEngine.Value[" + compute + "]";
         }
     }
 
@@ -852,7 +721,7 @@
      * {@link Language} objects to represent them. One can obtain a {@link #getName() name} or list
      * of supported {@link #getMimeTypes() MIME types} for each language. The actual language
      * implementation is not initialized until
-     * {@link PolyglotEngine#eval(java.lang.String, java.lang.String) a code is evaluated} in it.
+     * {@link PolyglotEngine#eval(com.oracle.truffle.api.source.Source) a code is evaluated} in it.
      */
     public class Language {
         private final LanguageCache info;
@@ -914,16 +783,8 @@
         public Value getGlobalObject() {
             checkThread();
 
-            Object[] res = {SPI.languageGlobal(getEnv(true)), null};
-            return res[0] == null ? null : new Value(new TruffleLanguage[]{info.getImpl(true)}, res, null);
-        }
-
-        /**
-         * @deprecated concatenate {@link #getName()} and {@link #getVersion()} the way you want.
-         */
-        @Deprecated
-        public String getShortName() {
-            return getName() + "(" + getVersion() + ")";
+            Object res = SPI.languageGlobal(getEnv(true));
+            return res == null ? null : new Value(new TruffleLanguage[]{info.getImpl(true)}, res);
         }
 
         TruffleLanguage<?> getImpl(boolean create) {
@@ -941,7 +802,7 @@
 
         @Override
         public String toString() {
-            return "[" + getShortName() + " for " + getMimeTypes() + "]";
+            return "[" + getName() + "@ " + getVersion() + " for " + getMimeTypes() + "]";
         }
     } // end of Language
 
@@ -957,7 +818,15 @@
                 return impl;
             }
         }
-        throw new IllegalStateException("Cannot find language " + languageClazz + " among " + langs);
+        return null;
+    }
+
+    TruffleLanguage<?> findLanguage(String mimeType) {
+        Language languageDescription = this.langs.get(mimeType);
+        if (languageDescription != null) {
+            return languageDescription.getImpl(true);
+        }
+        return null;
     }
 
     TruffleLanguage<?> findLanguage(Probe probe) {
@@ -1058,9 +927,19 @@
         }
 
         @Override
-        protected TruffleLanguage<?> findLanguageImpl(Object obj, Class<? extends TruffleLanguage> languageClazz) {
+        protected TruffleLanguage<?> findLanguageImpl(Object obj, Class<? extends TruffleLanguage> languageClazz, String mimeType) {
             final PolyglotEngine vm = (PolyglotEngine) obj;
-            return vm.findLanguage(languageClazz);
+            TruffleLanguage<?> language = null;
+            if (languageClazz != null) {
+                language = vm.findLanguage(languageClazz);
+            }
+            if (language == null && mimeType != null) {
+                language = vm.findLanguage(mimeType);
+            }
+            if (language == null) {
+                throw new IllegalStateException("Cannot find language " + languageClazz + " with mimeType" + mimeType + " among " + vm.langs);
+            }
+            return language;
         }
 
         @Override
--- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java	Tue Nov 10 19:42:37 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2014, 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.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-
-import com.oracle.truffle.api.TruffleLanguage;
-import com.oracle.truffle.api.debug.ExecutionEvent;
-import com.oracle.truffle.api.debug.SuspendedEvent;
-import com.oracle.truffle.api.source.Source;
-
-/**
- * @deprecated
- */
-@Deprecated
-@SuppressWarnings({"rawtypes", "deprecated"})
-public final class TruffleVM extends PolyglotEngine {
-    private TruffleVM() {
-        super();
-    }
-
-    /**
-     * Real constructor used from the builder.
-     */
-    TruffleVM(Executor executor, Map<String, Object> globals, OutputStream out, OutputStream err, InputStream in, EventConsumer<?>[] handlers) {
-        super(executor, globals, out, err, in, handlers);
-    }
-
-    @Deprecated
-    public static TruffleVM.Builder newVM() {
-        // making Builder non-static inner class is a
-        // nasty trick to avoid the Builder class to appear
-        // in Javadoc next to TruffleVM class
-        TruffleVM vm = new TruffleVM();
-        return vm.new Builder();
-    }
-
-    @SuppressWarnings("deprecation")
-    @Deprecated
-    public final class Builder extends PolyglotEngine.Builder {
-        Builder() {
-        }
-
-        @Deprecated
-        @Override
-        public Builder setOut(OutputStream os) {
-            super.setOut(os);
-            return this;
-        }
-
-        @Deprecated
-        @Override
-        public Builder executor(Executor executor) {
-            return (Builder) super.executor(executor);
-        }
-
-        @Deprecated
-        @Override
-        public Builder setErr(OutputStream os) {
-            super.setErr(os);
-            return this;
-        }
-
-        @Deprecated
-        @Override
-        public Builder globalSymbol(String name, Object obj) {
-            return (Builder) super.globalSymbol(name, obj);
-        }
-
-        @Deprecated
-        @Override
-        public Builder setIn(InputStream is) {
-            super.setIn(is);
-            return this;
-        }
-
-        @Deprecated
-        @Override
-        public Builder onEvent(EventConsumer<?> handler) {
-            return (Builder) super.onEvent(handler);
-        }
-
-        @Deprecated
-        @Override
-        public Builder stdIn(Reader r) {
-            return (Builder) super.stdIn(r);
-        }
-
-        @Deprecated
-        @Override
-        public Builder stdErr(Writer w) {
-            return (Builder) super.stdErr(w);
-        }
-
-        @Deprecated
-        @Override
-        public Builder stdOut(Writer w) {
-            return (Builder) super.stdOut(w);
-        }
-
-        @Deprecated
-        @Override
-        public TruffleVM build() {
-            return (TruffleVM) super.build();
-        }
-    }
-
-    @Override
-    Value createValue(TruffleLanguage[] lang, Object[] result, CountDownLatch ready) {
-        return new Symbol(lang, result, ready);
-    }
-
-    @Override
-    Language createLanguage(Map.Entry<String, LanguageCache> en) {
-        return new Language(en.getValue());
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public Map<String, Language> getLanguages() {
-        return (Map<String, Language>) super.getLanguages();
-    }
-
-    @Override
-    public Symbol eval(Source source) throws IOException {
-        return (Symbol) super.eval(source);
-    }
-
-    @Override
-    public Symbol findGlobalSymbol(final String globalName) {
-        return (Symbol) super.findGlobalSymbol(globalName);
-    }
-
-    @Override
-    void dispatchSuspendedEvent(SuspendedEvent event) {
-        super.dispatchSuspendedEvent(event);
-    }
-
-    @Override
-    void dispatchExecutionEvent(ExecutionEvent event) {
-        super.dispatchExecutionEvent(event);
-    }
-
-    @Deprecated
-    public class Symbol extends Value {
-        Symbol(TruffleLanguage<?>[] language, Object[] result, CountDownLatch ready) {
-            super(language, result, ready);
-        }
-
-        @Override
-        public Symbol invoke(final Object thiz, final Object... args) throws IOException {
-            return (Symbol) super.invoke(thiz, args);
-        }
-    }
-
-    @Deprecated
-    public final class Language extends PolyglotEngine.Language {
-        Language(LanguageCache info) {
-            super(info);
-        }
-    } // end of Language
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Wed Nov 11 15:59:56 2015 -0800
@@ -26,11 +26,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -401,11 +397,6 @@
             return in;
         }
 
-        @Deprecated
-        public Reader stdIn() {
-            return new InputStreamReader(in);
-        }
-
         /**
          * Standard output writer for {@link com.oracle.truffle.api.vm.PolyglotEngine} this language
          * is being executed in.
@@ -416,11 +407,6 @@
             return out;
         }
 
-        @Deprecated
-        public Writer stdOut() {
-            return new OutputStreamWriter(out);
-        }
-
         /**
          * Standard error writer for {@link com.oracle.truffle.api.vm.PolyglotEngine} this language
          * is being executed in.
@@ -431,11 +417,6 @@
             return err;
         }
 
-        @Deprecated
-        public Writer stdErr() {
-            return new OutputStreamWriter(err);
-        }
-
         public Instrumenter instrumenter() {
             return instrumenter;
         }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Wed Nov 11 15:59:56 2015 -0800
@@ -84,6 +84,11 @@
      */
     public static final boolean TraceASTJSON;
 
+    /**
+     * Forces ahead-of-time initialization.
+     */
+    public static final boolean AOT;
+
     private static NodeCost parseNodeInfoKind(String kind) {
         if (kind == null) {
             return null;
@@ -93,7 +98,7 @@
     }
 
     static {
-        final boolean[] values = new boolean[3];
+        final boolean[] values = new boolean[4];
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
                 values[0] = Boolean.getBoolean("truffle.TraceRewrites");
@@ -102,11 +107,13 @@
                 TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost"));
                 values[1] = Boolean.getBoolean("truffle.DetailedRewriteReasons");
                 values[2] = Boolean.getBoolean("truffle.TraceASTJSON");
+                values[3] = Boolean.getBoolean("com.oracle.truffle.aot");
                 return null;
             }
         });
         TraceRewrites = values[0];
         DetailedRewriteReasons = values[1];
         TraceASTJSON = values[2];
+        AOT = values[3];
     }
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java	Wed Nov 11 15:59:56 2015 -0800
@@ -423,7 +423,7 @@
                     doHalt(node, vFrame.materialize());
                 }
 
-                public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) {
+                public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception) {
                     doHalt(node, vFrame.materialize());
                 }
 
@@ -481,7 +481,7 @@
                     doHalt(node, vFrame.materialize());
                 }
 
-                public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) {
+                public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception) {
                     doHalt(node, vFrame.materialize());
                 }
 
@@ -564,7 +564,7 @@
                     doHalt(node, vFrame.materialize());
                 }
 
-                public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) {
+                public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception) {
                     doHalt(node, vFrame.materialize());
                 }
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java	Wed Nov 11 15:59:56 2015 -0800
@@ -44,7 +44,6 @@
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.debug.Debugger.BreakpointCallback;
 import com.oracle.truffle.api.debug.Debugger.WarningLog;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -368,7 +367,6 @@
             }
         }
 
-        @SuppressWarnings("rawtypes")
         private void attach(Probe newProbe) {
             if (getState() == DISPOSED) {
                 throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME);
@@ -378,8 +376,7 @@
             if (conditionSource == null) {
                 newInstrument = instrumenter.attach(newProbe, new UnconditionalLineBreakInstrumentListener(), BREAKPOINT_NAME);
             } else {
-                final Class<? extends TruffleLanguage> languageClass = Debugger.ACCESSOR.findLanguage(newProbe);
-                newInstrument = instrumenter.attach(newProbe, languageClass, conditionSource, this, BREAKPOINT_NAME);
+                newInstrument = instrumenter.attach(newProbe, conditionSource, this, BREAKPOINT_NAME, null);
             }
             instruments.add(newInstrument);
             changeState(isEnabled ? ENABLED : DISABLED);
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java	Wed Nov 11 15:59:56 2015 -0800
@@ -42,7 +42,6 @@
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.debug.Debugger.BreakpointCallback;
 import com.oracle.truffle.api.debug.Debugger.WarningLog;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -330,7 +329,6 @@
             }
         }
 
-        @SuppressWarnings("rawtypes")
         private void attach(Probe newProbe) {
             if (getState() == DISPOSED) {
                 throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME);
@@ -340,8 +338,7 @@
             if (conditionSource == null) {
                 newInstrument = instrumenter.attach(newProbe, new UnconditionalTagBreakInstrumentListener(), BREAKPOINT_NAME);
             } else {
-                final Class<? extends TruffleLanguage> languageClass = Debugger.ACCESSOR.findLanguage(newProbe);
-                instrumenter.attach(newProbe, languageClass, conditionSource, this, BREAKPOINT_NAME);
+                instrumenter.attach(newProbe, conditionSource, this, BREAKPOINT_NAME, null);
             }
             instruments.add(newInstrument);
             changeState(isEnabled ? ENABLED : DISABLED);
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Wed Nov 11 15:59:56 2015 -0800
@@ -33,6 +33,7 @@
 
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
@@ -179,7 +180,7 @@
     protected boolean isInstrumentable(Object vm, Node node) {
         final RootNode rootNode = node.getRootNode();
         Class<? extends TruffleLanguage> languageClazz = findLanguage(rootNode);
-        TruffleLanguage language = findLanguageImpl(vm, languageClazz);
+        TruffleLanguage language = findLanguageImpl(vm, languageClazz, null);
         return isInstrumentable(node, language);
     }
 
@@ -194,7 +195,7 @@
     protected WrapperNode createWrapperNode(Object vm, Node node) {
         final RootNode rootNode = node.getRootNode();
         Class<? extends TruffleLanguage> languageClazz = findLanguage(rootNode);
-        TruffleLanguage language = findLanguageImpl(vm, languageClazz);
+        TruffleLanguage language = findLanguageImpl(vm, languageClazz, null);
         return createWrapperNode(node, language);
     }
 
@@ -230,7 +231,7 @@
     }
 
     @SuppressWarnings("rawtypes")
-    protected TruffleLanguage<?> findLanguageImpl(Object known, Class<? extends TruffleLanguage> languageClass) {
+    protected TruffleLanguage<?> findLanguageImpl(Object known, Class<? extends TruffleLanguage> languageClass, String mimeType) {
         Object vm;
         if (known == null) {
             vm = CURRENT_VM.get();
@@ -240,7 +241,7 @@
         } else {
             vm = known;
         }
-        return SPI.findLanguageImpl(vm, languageClass);
+        return SPI.findLanguageImpl(vm, languageClass, mimeType);
     }
 
     protected Instrumenter getInstrumenter(Object known) {
@@ -267,6 +268,7 @@
     private static Reference<Object> previousVM = new WeakReference<>(null);
     private static Assumption oneVM = Truffle.getRuntime().createAssumption();
 
+    @TruffleBoundary
     @SuppressWarnings("unused")
     protected Closeable executionStart(Object vm, int currentDepth, Debugger debugger, Source s) {
         vm.getClass();
@@ -280,6 +282,7 @@
         }
         CURRENT_VM.set(vm);
         class ContextCloseable implements Closeable {
+            @TruffleBoundary
             @Override
             public void close() throws IOException {
                 CURRENT_VM.set(prev);
@@ -327,7 +330,7 @@
 
     @SuppressWarnings("rawtypes")
     protected CallTarget parse(Class<? extends TruffleLanguage> languageClass, Source code, Node context, String... argumentNames) throws IOException {
-        final TruffleLanguage<?> truffleLanguage = findLanguageImpl(null, languageClass);
+        final TruffleLanguage<?> truffleLanguage = findLanguageImpl(null, languageClass, code.getMimeType());
         return parse(truffleLanguage, code, context, argumentNames);
     }
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/EventHandlerNode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/EventHandlerNode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -54,7 +54,7 @@
     /**
      * An AST Node's execute method has just thrown an exception.
      */
-    public abstract void returnExceptional(Node node, VirtualFrame vFrame, Exception exception);
+    public abstract void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception);
 
     /**
      * Gets the {@link Probe} that manages this chain of event handling.
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java	Wed Nov 11 15:59:56 2015 -0800
@@ -46,6 +46,7 @@
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import java.util.Map;
 
 /**
  * Client access to instrumentation services in a Truffle execution environment.
@@ -478,11 +479,71 @@
      * @param listener optional client callback for results/failure notification
      * @param instrumentInfo instrumentInfo optional documentation about the Instrument
      * @return a handle for access to the binding
+     * @deprecated
      */
+    @Deprecated
     @SuppressWarnings("rawtypes")
     public ProbeInstrument attach(Probe probe, Class<? extends TruffleLanguage> languageClass, Source source, EvalInstrumentListener listener, String instrumentInfo) {
+        return attach(probe, languageClass, source, listener, instrumentInfo, new String[0], new Object[0]);
+    }
+
+    /**
+     * <em>Attaches</em> a fragment of source text that is to be evaluated just before execution
+     * enters the location of a {@link Probe}, creating a <em>binding</em> called an
+     * {@link ProbeInstrument}. The outcome of the evaluation is reported to an optional
+     * {@link EvalInstrumentListener listener}, but the outcome does not affect the flow of guest
+     * language execution, even if the evaluation produces an exception.
+     * <p>
+     * The source text is assumed to be expressed in the language identified by its associated
+     * {@linkplain Source#getMimeType() MIME type}, if specified, otherwise by the language
+     * associated with the AST location associated with the {@link Probe}.
+     * <p>
+     * The source text is parsed in the lexical context of the AST location associated with the
+     * {@link Probe}.
+     * <p>
+     * The source text executes subject to full Truffle optimization.
+     *
+     * @param probe source of AST execution events, non-null
+     * @param source the source code to be evaluated, non-null and non-empty, preferably with
+     *            {@link Source#withMimeType(java.lang.String) specified mime type} that determines
+     *            the {@link TruffleLanguage} to use when processing the source
+     * @param listener optional client callback for results/failure notification
+     * @param instrumentInfo instrumentInfo optional documentation about the Instrument
+     * @param parameters keys are the parameter names to pass to
+     *            {@link TruffleLanguage#parse(com.oracle.truffle.api.source.Source, com.oracle.truffle.api.nodes.Node, java.lang.String...)
+     *            parse} method; values will be passed to
+     *            {@link CallTarget#call(java.lang.Object...)} returned from the <code>parse</code>
+     *            method; the value can be <code>null</code>
+     * @return a handle for access to the binding
+     */
+    public ProbeInstrument attach(Probe probe, Source source, EvalInstrumentListener listener, String instrumentInfo, Map<String, Object> parameters) {
+        final int size = parameters == null ? 0 : parameters.size();
+        String[] names = new String[size];
+        Object[] params = new Object[size];
+        if (parameters != null) {
+            int index = 0;
+            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
+                names[index] = entry.getKey();
+                params[index] = entry.getValue();
+                index++;
+            }
+        }
+        return attach(probe, null, source, listener, instrumentInfo, names, params);
+    }
+
+    @SuppressWarnings("rawtypes")
+    private ProbeInstrument attach(Probe probe, Class<? extends TruffleLanguage> languageClass, Source source, EvalInstrumentListener listener, String instrumentInfo, String[] argumentNames,
+                    Object[] parameters) {
         assert probe.getInstrumenter() == this;
-        final EvalInstrument instrument = new EvalInstrument(languageClass, source, listener, instrumentInfo);
+        Class<? extends TruffleLanguage> foundLanguageClass = null;
+        if (languageClass == null) {
+            if (source.getMimeType() == null) {
+                foundLanguageClass = ACCESSOR.findLanguage(probe);
+            }
+        } else {
+            foundLanguageClass = languageClass;
+        }
+        final EvalInstrument instrument = new EvalInstrument(foundLanguageClass, source, listener, instrumentInfo, argumentNames, parameters);
         probe.attach(instrument);
         return instrument;
     }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java	Wed Nov 11 15:59:56 2015 -0800
@@ -54,10 +54,7 @@
  * @see Instrumenter
  */
 public abstract class ProbeInstrument extends Instrument {
-
-    private static final String[] NO_ARGS = new String[0];
-
-    protected Probe probe = null;
+    Probe probe = null;
 
     /**
      * <h4>Implementation Notes</h4>
@@ -223,7 +220,7 @@
             }
 
             @Override
-            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+            public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) {
                 SimpleInstrument.this.simpleListener.onReturnExceptional(SimpleInstrument.this.probe, exception);
                 if (nextInstrumentNode != null) {
                     nextInstrumentNode.returnExceptional(node, vFrame, exception);
@@ -315,7 +312,7 @@
             }
 
             @Override
-            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+            public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) {
                 standardListener.onReturnExceptional(StandardInstrument.this.probe, node, vFrame, exception);
                 if (nextInstrumentNode != null) {
                     nextInstrumentNode.returnExceptional(node, vFrame, exception);
@@ -345,13 +342,17 @@
         @SuppressWarnings("rawtypes") private final Class<? extends TruffleLanguage> languageClass;
         private final Source source;
         private final EvalInstrumentListener evalListener;
+        private final String[] names;
+        private final Object[] params;
 
         @SuppressWarnings("rawtypes")
-        EvalInstrument(Class<? extends TruffleLanguage> languageClass, Source source, EvalInstrumentListener evalListener, String instrumentInfo) {
+        EvalInstrument(Class<? extends TruffleLanguage> languageClass, Source source, EvalInstrumentListener evalListener, String instrumentInfo, String[] argumentNames, Object[] parameters) {
             super(instrumentInfo);
             this.languageClass = languageClass;
             this.source = source;
             this.evalListener = evalListener;
+            this.names = argumentNames;
+            this.params = parameters;
         }
 
         @Override
@@ -392,7 +393,7 @@
             public void enter(Node node, VirtualFrame vFrame) {
                 if (callNode == null) {
                     try {
-                        final CallTarget callTarget = Instrumenter.ACCESSOR.parse(languageClass, source, node, NO_ARGS);
+                        final CallTarget callTarget = Instrumenter.ACCESSOR.parse(languageClass, source, node, names);
                         if (callTarget != null) {
                             callNode = Truffle.getRuntime().createDirectCallNode(callTarget);
                             callNode.forceInlining();
@@ -407,7 +408,7 @@
                 }
                 if (callNode != null) {
                     try {
-                        final Object result = callNode.call(vFrame, NO_ARGS);
+                        final Object result = callNode.call(vFrame, params);
                         if (evalListener != null) {
                             evalListener.onExecution(node, vFrame, result);
                         }
@@ -437,7 +438,7 @@
             }
 
             @Override
-            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+            public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) {
                 if (nextInstrumentNode != null) {
                     nextInstrumentNode.returnExceptional(node, vFrame, exception);
                 }
@@ -524,7 +525,7 @@
             }
 
             @Override
-            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+            public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) {
                 if (nextInstrumentNode != null) {
                     nextInstrumentNode.returnExceptional(node, vFrame, exception);
                 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -110,7 +110,7 @@
     }
 
     @Override
-    public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+    public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) {
         if (exception instanceof KillException) {
             throw (KillException) exception;
         }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java	Wed Nov 11 15:59:56 2015 -0800
@@ -74,5 +74,5 @@
      * <p>
      * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
      */
-    void onReturnExceptional(Probe probe, Exception exception);
+    void onReturnExceptional(Probe probe, Throwable exception);
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardAfterInstrumentListener.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardAfterInstrumentListener.java	Wed Nov 11 15:59:56 2015 -0800
@@ -68,5 +68,5 @@
      * <p>
      * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
      */
-    void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception);
+    void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception);
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java	Wed Nov 11 15:59:56 2015 -0800
@@ -74,5 +74,5 @@
      * <p>
      * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
      */
-    void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception);
+    void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception);
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java	Wed Nov 11 15:59:56 2015 -0800
@@ -41,6 +41,6 @@
     public void onReturnValue(Probe probe, Object result) {
     }
 
-    public void onReturnExceptional(Probe probe, Exception exception) {
+    public void onReturnExceptional(Probe probe, Throwable exception) {
     }
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java	Wed Nov 11 15:59:56 2015 -0800
@@ -44,7 +44,6 @@
     public void onReturnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) {
     }
 
-    public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) {
+    public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception) {
     }
-
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -99,21 +99,6 @@
     public abstract void forceInlining();
 
     /**
-     * Returns true if the runtime system has decided to inline this call-site. If the
-     * {@link DirectCallNode} was forced to inline then this does not necessarily mean that the
-     * {@link DirectCallNode} is really going to be inlined. This depends on whether or not the
-     * runtime system supports inlining. The runtime system may also decide to not inline calls
-     * which were forced to inline.
-     *
-     * @deprecated we do not expose this information any longer. returns always false.
-     */
-    @SuppressWarnings("static-method")
-    @Deprecated
-    public final boolean isInlined() {
-        return false;
-    }
-
-    /**
      * Returns <code>true</code> if the runtime system supports cloning and the {@link RootNode}
      * returns <code>true</code> in {@link RootNode#isCloningAllowed()}.
      *
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Wed Nov 11 15:59:56 2015 -0800
@@ -24,111 +24,243 @@
  */
 package com.oracle.truffle.api.nodes;
 
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.StringWriter;
+import java.io.OutputStream;
+import java.io.PrintStream;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.net.Socket;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.IdentityHashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import com.oracle.truffle.api.TruffleOptions;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 
 /**
  * Utility class for creating output for the ideal graph visualizer.
  */
-public class GraphPrintVisitor {
+public class GraphPrintVisitor implements Closeable {
 
     public static final String GraphVisualizerAddress = "127.0.0.1";
     public static final int GraphVisualizerPort = 4444;
+    private static final String DEFAULT_GRAPH_NAME = "truffle tree";
 
-    private Document dom;
-    private Map<Object, Element> nodeMap;
-    private List<Element> edgeList;
-    private Map<Object, Element> prevNodeMap;
+    private Map<Object, NodeElement> nodeMap;
+    private List<EdgeElement> edgeList;
+    private Map<Object, NodeElement> prevNodeMap;
     private int id;
-    private Element graphDocument;
-    private Element groupElement;
-    private Element graphElement;
-    private Element nodesElement;
-    private Element edgesElement;
+    private Impl xmlstream;
+    private OutputStream outputStream;
+    private int openGroupCount;
+    private int openGraphCount;
+    private String currentGraphName;
+
+    private static class NodeElement {
+        private final int id;
+        private final Map<String, Object> properties;
+
+        public NodeElement(int id) {
+            super();
+            this.id = id;
+            this.properties = new LinkedHashMap<>();
+        }
+
+        public int getId() {
+            return id;
+        }
+
+        public Map<String, Object> getProperties() {
+            return properties;
+        }
+    }
+
+    private static class EdgeElement {
+        private final NodeElement from;
+        private final NodeElement to;
+        private final int index;
+        private final String label;
+
+        public EdgeElement(NodeElement from, NodeElement to, int index, String label) {
+            this.from = from;
+            this.to = to;
+            this.index = index;
+            this.label = label;
+        }
+
+        public NodeElement getFrom() {
+            return from;
+        }
+
+        public NodeElement getTo() {
+            return to;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public String getLabel() {
+            return label;
+        }
+    }
+
+    private static class Impl {
+        private static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance();
+        private final XMLStreamWriter xmlstream;
+
+        protected Impl(OutputStream outputStream) {
+            try {
+                this.xmlstream = XML_OUTPUT_FACTORY.createXMLStreamWriter(outputStream);
+            } catch (XMLStreamException | FactoryConfigurationError e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void writeStartDocument() {
+            try {
+                xmlstream.writeStartDocument();
+            } catch (XMLStreamException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void writeEndDocument() {
+            try {
+                xmlstream.writeEndDocument();
+            } catch (XMLStreamException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void writeStartElement(String name) {
+            try {
+                xmlstream.writeStartElement(name);
+            } catch (XMLStreamException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void writeEndElement() {
+            try {
+                xmlstream.writeEndElement();
+            } catch (XMLStreamException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void writeAttribute(String name, String value) {
+            try {
+                xmlstream.writeAttribute(name, value);
+            } catch (XMLStreamException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void writeCharacters(String text) {
+            try {
+                xmlstream.writeCharacters(text);
+            } catch (XMLStreamException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void flush() {
+            try {
+                xmlstream.flush();
+            } catch (XMLStreamException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void close() {
+            try {
+                xmlstream.close();
+            } catch (XMLStreamException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
 
     public GraphPrintVisitor() {
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        try {
-            DocumentBuilder db = dbf.newDocumentBuilder();
+        this(new ByteArrayOutputStream());
+    }
 
-            dom = db.newDocument();
-        } catch (ParserConfigurationException ex) {
-            throw new RuntimeException(ex);
+    public GraphPrintVisitor(OutputStream outputStream) {
+        this.outputStream = outputStream;
+        this.xmlstream = new Impl(outputStream);
+        this.xmlstream.writeStartDocument();
+        this.xmlstream.writeStartElement("graphDocument");
+    }
+
+    private void ensureOpen() {
+        if (xmlstream == null) {
+            throw new IllegalStateException("printer is closed");
         }
-
-        graphDocument = dom.createElement("graphDocument");
-        dom.appendChild(graphDocument);
     }
 
     public GraphPrintVisitor beginGroup(String groupName) {
-        groupElement = dom.createElement("group");
-        graphDocument.appendChild(groupElement);
-        Element properties = dom.createElement("properties");
-        groupElement.appendChild(properties);
+        ensureOpen();
+        maybeEndGraph();
+        openGroupCount++;
+        xmlstream.writeStartElement("group");
+        xmlstream.writeStartElement("properties");
 
         if (!groupName.isEmpty()) {
             // set group name
-            Element propName = dom.createElement("p");
-            propName.setAttribute("name", "name");
-            propName.setTextContent(groupName);
-            properties.appendChild(propName);
+            xmlstream.writeStartElement("p");
+            xmlstream.writeAttribute("name", "name");
+            xmlstream.writeCharacters(groupName);
+            xmlstream.writeEndElement();
         }
 
+        xmlstream.writeEndElement(); // properties
+
         // forget old nodes
-        nodeMap = prevNodeMap = null;
-        edgeList = null;
+        prevNodeMap = null;
+        nodeMap = new IdentityHashMap<>();
+        edgeList = new ArrayList<>();
+
+        return this;
+    }
+
+    public GraphPrintVisitor endGroup() {
+        ensureOpen();
+        if (openGroupCount <= 0) {
+            throw new IllegalArgumentException("no open group");
+        }
+        maybeEndGraph();
+        openGroupCount--;
+
+        xmlstream.writeEndElement(); // group
 
         return this;
     }
 
     public GraphPrintVisitor beginGraph(String graphName) {
-        if (null == groupElement) {
-            beginGroup("");
-        } else if (null != prevNodeMap) {
-            // TODO: difference (create removeNode,removeEdge elements)
+        ensureOpen();
+        if (openGroupCount == 0) {
+            beginGroup(graphName);
         }
+        maybeEndGraph();
+        openGraphCount++;
 
-        graphElement = dom.createElement("graph");
-        groupElement.appendChild(graphElement);
-        Element properties = dom.createElement("properties");
-        graphElement.appendChild(properties);
-        nodesElement = dom.createElement("nodes");
-        graphElement.appendChild(nodesElement);
-        edgesElement = dom.createElement("edges");
-        graphElement.appendChild(edgesElement);
-
-        // set graph name
-        Element propName = dom.createElement("p");
-        propName.setAttribute("name", "name");
-        propName.setTextContent(graphName);
-        properties.appendChild(propName);
+        this.currentGraphName = graphName;
 
         // save old nodes
         prevNodeMap = nodeMap;
@@ -138,92 +270,156 @@
         return this;
     }
 
+    private void maybeEndGraph() {
+        if (openGraphCount > 0) {
+            endGraph();
+            assert openGraphCount == 0;
+        }
+    }
+
+    public GraphPrintVisitor endGraph() {
+        ensureOpen();
+        if (openGraphCount <= 0) {
+            throw new IllegalArgumentException("no open graph");
+        }
+        openGraphCount--;
+
+        xmlstream.writeStartElement("graph");
+
+        xmlstream.writeStartElement("properties");
+
+        // set graph name
+        xmlstream.writeStartElement("p");
+        xmlstream.writeAttribute("name", "name");
+        xmlstream.writeCharacters(currentGraphName);
+        xmlstream.writeEndElement();
+
+        xmlstream.writeEndElement(); // properties
+
+        xmlstream.writeStartElement("nodes");
+        writeNodes();
+        xmlstream.writeEndElement(); // nodes
+
+        xmlstream.writeStartElement("edges");
+        writeEdges();
+        xmlstream.writeEndElement(); // edges
+
+        xmlstream.writeEndElement(); // graph
+
+        xmlstream.flush();
+
+        return this;
+    }
+
+    private void writeNodes() {
+        for (NodeElement node : nodeMap.values()) {
+            xmlstream.writeStartElement("node");
+            xmlstream.writeAttribute("id", String.valueOf(node.getId()));
+
+            xmlstream.writeStartElement("properties");
+            for (Map.Entry<String, Object> property : node.getProperties().entrySet()) {
+                xmlstream.writeStartElement("p");
+                xmlstream.writeAttribute("name", property.getKey());
+                xmlstream.writeCharacters(safeToString(property.getValue()));
+                xmlstream.writeEndElement(); // p
+            }
+            xmlstream.writeEndElement(); // properties
+
+            xmlstream.writeEndElement(); // node
+        }
+    }
+
+    private void writeEdges() {
+        for (EdgeElement edge : edgeList) {
+            xmlstream.writeStartElement("edge");
+
+            xmlstream.writeAttribute("from", String.valueOf(edge.getFrom().getId()));
+            xmlstream.writeAttribute("to", String.valueOf(edge.getTo().getId()));
+            xmlstream.writeAttribute("index", String.valueOf(edge.getIndex()));
+            if (edge.getLabel() != null) {
+                xmlstream.writeAttribute("label", edge.getLabel());
+            }
+
+            xmlstream.writeEndElement(); // edge
+        }
+    }
+
     @Override
     public String toString() {
-        if (null != dom) {
-            try {
-                Transformer tr = TransformerFactory.newInstance().newTransformer();
-                tr.setOutputProperty(OutputKeys.INDENT, "yes");
-                tr.setOutputProperty(OutputKeys.METHOD, "xml");
-                tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
-
-                StringWriter strWriter = new StringWriter();
-                tr.transform(new DOMSource(dom), new StreamResult(strWriter));
-                return strWriter.toString();
-            } catch (TransformerException e) {
-                e.printStackTrace();
-            }
+        if (outputStream instanceof ByteArrayOutputStream) {
+            return new String(((ByteArrayOutputStream) outputStream).toByteArray(), Charset.forName("UTF-8"));
         }
-        return "";
+        return super.toString();
     }
 
     public void printToFile(File f) {
-        try {
-            Transformer tr = TransformerFactory.newInstance().newTransformer();
-            tr.setOutputProperty(OutputKeys.INDENT, "yes");
-            tr.setOutputProperty(OutputKeys.METHOD, "xml");
-            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
-
-            tr.transform(new DOMSource(dom), new StreamResult(new FileOutputStream(f)));
-        } catch (TransformerException | FileNotFoundException e) {
-            e.printStackTrace();
+        close();
+        if (outputStream instanceof ByteArrayOutputStream) {
+            try (OutputStream os = new FileOutputStream(f)) {
+                os.write(((ByteArrayOutputStream) outputStream).toByteArray());
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
         }
     }
 
     public void printToSysout() {
-        try {
-            Transformer tr = TransformerFactory.newInstance().newTransformer();
-            tr.setOutputProperty(OutputKeys.INDENT, "yes");
-            tr.setOutputProperty(OutputKeys.METHOD, "xml");
-            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
-
-            tr.transform(new DOMSource(dom), new StreamResult(System.out));
-        } catch (TransformerException e) {
-            e.printStackTrace();
+        close();
+        if (outputStream instanceof ByteArrayOutputStream) {
+            PrintStream out = System.out;
+            out.println(toString());
         }
     }
 
     public void printToNetwork(boolean ignoreErrors) {
-        try {
-            Transformer tr = TransformerFactory.newInstance().newTransformer();
-            tr.setOutputProperty(OutputKeys.METHOD, "xml");
-
-            Socket socket = new Socket(GraphVisualizerAddress, GraphVisualizerPort);
-            BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000);
-            tr.transform(new DOMSource(dom), new StreamResult(stream));
-        } catch (TransformerException | IOException e) {
+        close();
+        try (Socket socket = new Socket(GraphVisualizerAddress, GraphVisualizerPort); BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream(), 0x4000)) {
+            os.write(((ByteArrayOutputStream) outputStream).toByteArray());
+        } catch (IOException e) {
             if (!ignoreErrors) {
                 e.printStackTrace();
             }
         }
     }
 
-    private String nextId() {
-        return String.valueOf(id++);
+    public void close() {
+        if (xmlstream == null) {
+            return;
+        }
+        while (openGroupCount > 0) {
+            endGroup();
+        }
+        assert openGraphCount == 0 && openGroupCount == 0;
+
+        xmlstream.writeEndElement(); // graphDocument
+        xmlstream.writeEndDocument();
+        xmlstream.flush();
+        xmlstream.close();
+        xmlstream = null;
     }
 
-    private String oldOrNextId(Object node) {
+    private int nextId() {
+        return id++;
+    }
+
+    private int oldOrNextId(Object node) {
         if (null != prevNodeMap && prevNodeMap.containsKey(node)) {
-            Element nodeElem = prevNodeMap.get(node);
-            return nodeElem.getAttribute("id");
+            NodeElement nodeElem = prevNodeMap.get(node);
+            return nodeElem.getId();
         } else {
             return nextId();
         }
     }
 
-    protected Element getElementByObject(Object op) {
-        return nodeMap.get(op);
+    protected NodeElement getElementByObject(Object obj) {
+        return nodeMap.get(obj);
     }
 
     protected void createElementForNode(Object node) {
         boolean exists = nodeMap.containsKey(node);
-        if (!exists || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) {
-            Element nodeElem = dom.createElement("node");
-            nodeElem.setAttribute("id", !exists ? oldOrNextId(node) : nextId());
-            nodeMap.put(node, nodeElem);
-            Element properties = dom.createElement("properties");
-            nodeElem.appendChild(properties);
-            nodesElement.appendChild(nodeElem);
+        if (!exists) {
+            int nodeId = !exists ? oldOrNextId(node) : nextId();
+            nodeMap.put(node, new NodeElement(nodeId));
 
             setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", ""));
             NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class);
@@ -241,33 +437,9 @@
         }
     }
 
-    private Element getPropertyElement(Object node, String propertyName) {
-        Element nodeElem = getElementByObject(node);
-        Element propertiesElem = (Element) nodeElem.getElementsByTagName("properties").item(0);
-        if (propertiesElem == null) {
-            return null;
-        }
-
-        NodeList propList = propertiesElem.getElementsByTagName("p");
-        for (int i = 0; i < propList.getLength(); i++) {
-            Element p = (Element) propList.item(i);
-            if (propertyName.equals(p.getAttribute("name"))) {
-                return p;
-            }
-        }
-        return null;
-    }
-
     protected void setNodeProperty(Object node, String propertyName, Object value) {
-        Element nodeElem = getElementByObject(node);
-        Element propElem = getPropertyElement(node, propertyName); // if property exists, replace
-        // its value
-        if (null == propElem) { // if property doesn't exist, create one
-            propElem = dom.createElement("p");
-            propElem.setAttribute("name", propertyName);
-            nodeElem.getElementsByTagName("properties").item(0).appendChild(propElem);
-        }
-        propElem.setTextContent(String.valueOf(value));
+        NodeElement nodeElem = getElementByObject(node);
+        nodeElem.getProperties().put(propertyName, value);
     }
 
     private void copyDebugProperties(Node node) {
@@ -278,11 +450,11 @@
     }
 
     private void readNodeProperties(Node node) {
-        NodeFieldAccessor[] fields = node.getNodeClass().getFields();
+        NodeFieldAccessor[] fields = NodeClass.get(node).getFields();
         for (NodeFieldAccessor field : fields) {
             if (field.getKind() == NodeFieldKind.DATA) {
                 String key = field.getName();
-                if (getPropertyElement(node, key) == null) {
+                if (!getElementByObject(node).getProperties().containsKey(key)) {
                     Object value = field.loadValue(node);
                     setNodeProperty(node, key, value);
                 }
@@ -291,71 +463,66 @@
     }
 
     protected void connectNodes(Object a, Object b, String label) {
-        if (nodeMap.get(a) == null || nodeMap.get(b) == null) {
+        NodeElement fromNode = getElementByObject(a);
+        NodeElement toNode = getElementByObject(b);
+        if (fromNode == null || toNode == null) {
             return;
         }
 
-        String fromId = nodeMap.get(a).getAttribute("id");
-        String toId = nodeMap.get(b).getAttribute("id");
-
         // count existing to-edges
         int count = 0;
-        for (Element e : edgeList) {
-            if (e.getAttribute("to").equals(toId)) {
+        for (EdgeElement e : edgeList) {
+            if (e.getTo() == toNode) {
                 ++count;
             }
         }
 
-        Element edgeElem = dom.createElement("edge");
-        edgeElem.setAttribute("from", fromId);
-        edgeElem.setAttribute("to", toId);
-        edgeElem.setAttribute("index", String.valueOf(count));
-        if (label != null) {
-            edgeElem.setAttribute("label", label);
-        }
-        edgesElement.appendChild(edgeElem);
-        edgeList.add(edgeElem);
+        edgeList.add(new EdgeElement(fromNode, toNode, count, label));
     }
 
     public GraphPrintVisitor visit(Object node) {
-        if (null == graphElement) {
-            beginGraph("truffle tree");
+        if (openGraphCount == 0) {
+            beginGraph(DEFAULT_GRAPH_NAME);
         }
 
         // if node is visited once again, skip
-        if (getElementByObject(node) != null && NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) == null) {
+        if (getElementByObject(node) != null) {
             return this;
         }
 
         // respect node's custom handler
-        if (NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) {
-            Class<? extends GraphPrintHandler> customHandlerClass = NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler();
-            try {
-                GraphPrintHandler customHandler = customHandlerClass.newInstance();
-                customHandler.visit(node, new GraphPrintAdapter());
-            } catch (InstantiationException | IllegalAccessException e) {
-                assert false : e;
-            }
+        if (!TruffleOptions.AOT && NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) {
+            visit(node, createGraphPrintHandlerFromClass(NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler()));
         } else if (NodeUtil.findAnnotation(node.getClass(), NullGraphPrintHandler.class) != null) {
             // ignore
         } else {
-            // default handler
-            createElementForNode(node);
-
-            if (node instanceof Node) {
-                for (Map.Entry<String, Node> child : findNamedNodeChildren((Node) node).entrySet()) {
-                    visit(child.getValue());
-                    connectNodes(node, child.getValue(), child.getKey());
-                }
-            }
+            visit(node, new DefaultGraphPrintHandler());
         }
 
         return this;
     }
 
+    public GraphPrintVisitor visit(Object node, GraphPrintHandler handler) {
+        if (openGraphCount == 0) {
+            beginGraph(DEFAULT_GRAPH_NAME);
+        }
+
+        handler.visit(node, new GraphPrintAdapter());
+
+        return this;
+    }
+
+    private static GraphPrintHandler createGraphPrintHandlerFromClass(Class<? extends GraphPrintHandler> customHandlerClass) {
+        try {
+            return customHandlerClass.newInstance();
+        } catch (InstantiationException | IllegalAccessException e) {
+            throw new AssertionError(e);
+        }
+    }
+
     private static LinkedHashMap<String, Node> findNamedNodeChildren(Node node) {
         LinkedHashMap<String, Node> nodes = new LinkedHashMap<>();
-        NodeClass nodeClass = node.getNodeClass();
+        NodeClass nodeClass = NodeClass.get(node);
 
         for (NodeFieldAccessor field : nodeClass.getFields()) {
             NodeFieldKind kind = field.getKind();
@@ -379,6 +546,14 @@
         return nodes;
     }
 
+    private static String safeToString(Object value) {
+        try {
+            return String.valueOf(value);
+        } catch (Throwable ex) {
+            return value.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(value));
+        }
+    }
+
     public class GraphPrintAdapter {
 
         public void createElementForNode(Object node) {
@@ -389,27 +564,43 @@
             GraphPrintVisitor.this.visit(node);
         }
 
+        public void visit(Object node, GraphPrintHandler handler) {
+            GraphPrintVisitor.this.visit(node, handler);
+        }
+
         public void connectNodes(Object node, Object child) {
             GraphPrintVisitor.this.connectNodes(node, child, null);
         }
 
+        public void connectNodes(Object node, Object child, String label) {
+            GraphPrintVisitor.this.connectNodes(node, child, label);
+        }
+
         public void setNodeProperty(Object node, String propertyName, Object value) {
             GraphPrintVisitor.this.setNodeProperty(node, propertyName, value);
         }
+
+        public boolean visited(Object node) {
+            return GraphPrintVisitor.this.getElementByObject(node) != null;
+        }
     }
 
     public interface GraphPrintHandler {
 
-        void visit(Object node, GraphPrintAdapter gPrinter);
+        void visit(Object node, GraphPrintAdapter printer);
     }
 
-    public interface ChildSupplier {
+    private static final class DefaultGraphPrintHandler implements GraphPrintHandler {
+        public void visit(Object node, GraphPrintAdapter printer) {
+            printer.createElementForNode(node);
 
-        /** Supplies an additional child if available. */
-        Object startNode(Object callNode);
-
-        void endNode(Object callNode);
-
+            if (node instanceof Node) {
+                for (Map.Entry<String, Node> child : findNamedNodeChildren((Node) node).entrySet()) {
+                    printer.visit(child.getValue());
+                    printer.connectNodes(node, child.getValue(), child.getKey());
+                }
+            }
+        }
     }
 
     @Retention(RetentionPolicy.RUNTIME)
@@ -423,14 +614,4 @@
     @Target(ElementType.TYPE)
     public @interface NullGraphPrintHandler {
     }
-
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.TYPE)
-    public @interface GraphDuplicate {
-    }
-
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface HiddenField {
-    }
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Wed Nov 11 15:59:56 2015 -0800
@@ -392,16 +392,6 @@
     }
 
     /**
-     * This method must never be called. It enforces that {@link Object#clone} is not directly
-     * called by subclasses. Use the {@link #copy()} method instead.
-     */
-    @Override
-    @Deprecated
-    protected final Object clone() throws CloneNotSupportedException {
-        throw new IllegalStateException("This method should never be called, use the copy method instead!");
-    }
-
-    /**
      * Get the root node of the tree a node belongs to.
      *
      * @return the {@link RootNode} or {@code null} if there is none.
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java	Wed Nov 11 15:59:56 2015 -0800
@@ -53,6 +53,8 @@
         }
     };
 
+    private static final NodeFieldAccessor[] EMPTY_NODE_FIELD_ARRAY = new NodeFieldAccessor[0];
+
     // The comprehensive list of all fields.
     private final NodeFieldAccessor[] fields;
     // Separate arrays for the frequently accessed fields.
@@ -68,11 +70,11 @@
         return nodeClasses.get(clazz);
     }
 
-    public static NodeClass get(Node clazz) {
-        return clazz.getNodeClass();
+    public static NodeClass get(Node node) {
+        return node.getNodeClass();
     }
 
-    public NodeClass(Class<? extends Node> clazz) {
+    NodeClass(Class<? extends Node> clazz) {
         List<NodeFieldAccessor> fieldsList = new ArrayList<>();
         NodeFieldAccessor parentFieldTmp = null;
         NodeFieldAccessor nodeClassFieldTmp = null;
@@ -115,12 +117,12 @@
             throw new AssertionError("parent field not found");
         }
 
-        this.fields = fieldsList.toArray(new NodeFieldAccessor[fieldsList.size()]);
+        this.fields = fieldsList.toArray(EMPTY_NODE_FIELD_ARRAY);
         this.nodeClassField = nodeClassFieldTmp;
         this.parentField = parentFieldTmp;
-        this.childFields = childFieldList.toArray(new NodeFieldAccessor[childFieldList.size()]);
-        this.childrenFields = childrenFieldList.toArray(new NodeFieldAccessor[childrenFieldList.size()]);
-        this.cloneableFields = cloneableFieldList.toArray(new NodeFieldAccessor[cloneableFieldList.size()]);
+        this.childFields = childFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
+        this.childrenFields = childrenFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
+        this.cloneableFields = cloneableFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
         this.clazz = clazz;
     }
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Nov 11 15:59:56 2015 -0800
@@ -421,9 +421,11 @@
         if (clazz.getAnnotation(annotationClass) != null) {
             return clazz.getAnnotation(annotationClass);
         } else {
-            for (Class<?> intf : clazz.getInterfaces()) {
-                if (intf.getAnnotation(annotationClass) != null) {
-                    return intf.getAnnotation(annotationClass);
+            if (!TruffleOptions.AOT) {
+                for (Class<?> intf : clazz.getInterfaces()) {
+                    if (intf.getAnnotation(annotationClass) != null) {
+                        return intf.getAnnotation(annotationClass);
+                    }
                 }
             }
             if (clazz.getSuperclass() != null) {
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -49,33 +49,6 @@
     @CompilationFinal private FrameDescriptor frameDescriptor;
 
     /**
-     * @deprecated each RootNode should be associated with a {@link TruffleLanguage} use constructor
-     *             that allows you to specify it. This method will be removed on Aug 15, 2015.
-     */
-    @Deprecated
-    protected RootNode() {
-        this(null, null, null, false);
-    }
-
-    /**
-     * @deprecated each RootNode should be associated with a {@link TruffleLanguage} use constructor
-     *             that allows you to specify it. This method will be removed on Aug 15, 2015.
-     */
-    @Deprecated
-    protected RootNode(SourceSection sourceSection) {
-        this(null, sourceSection, null, false);
-    }
-
-    /**
-     * @deprecated each RootNode should be associated with a {@link TruffleLanguage} use constructor
-     *             that allows you to specify it. This method will be removed on Aug 15, 2015.
-     */
-    @Deprecated
-    protected RootNode(SourceSection sourceSection, FrameDescriptor frameDescriptor) {
-        this(null, sourceSection, frameDescriptor, false);
-    }
-
-    /**
      * Creates new root node. Each {@link RootNode} is associated with a particular language - if
      * the root node represents a method it is assumed the method is written in such language.
      * <p>
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java	Wed Nov 11 15:59:56 2015 -0800
@@ -24,10 +24,11 @@
  */
 package com.oracle.truffle.api.utilities;
 
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Holds an {@link Assumption}, and knows how to recreate it with the same properties on
@@ -39,22 +40,24 @@
 public class CyclicAssumption {
 
     private final String name;
-    private final AtomicReference<Assumption> assumption;
+    private volatile Assumption assumption;
+
+    private static final AtomicReferenceFieldUpdater<CyclicAssumption, Assumption> ASSUMPTION_UPDATER = AtomicReferenceFieldUpdater.newUpdater(CyclicAssumption.class, Assumption.class, "assumption");
 
     public CyclicAssumption(String name) {
         this.name = name;
-        this.assumption = new AtomicReference<>(Truffle.getRuntime().createAssumption(name));
+        this.assumption = Truffle.getRuntime().createAssumption(name);
     }
 
     @TruffleBoundary
     public void invalidate() {
         Assumption newAssumption = Truffle.getRuntime().createAssumption(name);
-        Assumption oldAssumption = assumption.getAndSet(newAssumption);
+        Assumption oldAssumption = ASSUMPTION_UPDATER.getAndSet(this, newAssumption);
         oldAssumption.invalidate();
     }
 
     public Assumption getAssumption() {
-        return assumption.get();
+        return assumption;
     }
 
 }
--- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java	Wed Nov 11 15:59:56 2015 -0800
@@ -23,6 +23,7 @@
 package com.oracle.truffle.dsl.processor.java.compiler;
 
 import com.oracle.truffle.dsl.processor.java.ElementUtils;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -31,6 +32,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
+
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
@@ -47,13 +49,21 @@
         }
     }
 
+    /**
+     * @see "https://bugs.openjdk.java.net/browse/JDK-8039214"
+     */
+    @SuppressWarnings("unused")
+    private static List<Element> newElementList(List<? extends Element> src) {
+        List<Element> workaround = new ArrayList<Element>(src);
+        return workaround;
+    }
+
     public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
-        return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type)));
-
+        return sortBySourceOrder(newElementList(environment.getElementUtils().getAllMembers(type)));
     }
 
     public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
-        return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements()));
+        return sortBySourceOrder(newElementList(type.getEnclosedElements()));
     }
 
     private static List<? extends Element> sortBySourceOrder(List<Element> elements) {
--- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Wed Nov 11 15:59:56 2015 -0800
@@ -72,20 +72,21 @@
     }
 
     public boolean isCacheBoundByGuard(CacheExpression cacheExpression) {
+        VariableElement cachedVariable = cacheExpression.getParameter().getVariableElement();
+
         for (GuardExpression expression : getGuards()) {
-            if (expression.getExpression().findBoundVariableElements().contains(cacheExpression.getParameter().getVariableElement())) {
+            if (expression.getExpression().findBoundVariableElements().contains(cachedVariable)) {
                 return true;
             }
         }
 
-        // check all next binding caches if they are bound by guard
-        Set<VariableElement> boundVariables = cacheExpression.getExpression().findBoundVariableElements();
+        // check all next binding caches if they are bound to a guard and use this cache variable
         boolean found = false;
         for (CacheExpression expression : getCaches()) {
             if (cacheExpression == expression) {
                 found = true;
             } else if (found) {
-                if (boundVariables.contains(expression.getParameter().getVariableElement())) {
+                if (expression.getExpression().findBoundVariableElements().contains(cachedVariable)) {
                     if (isCacheBoundByGuard(expression)) {
                         return true;
                     }
--- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Wed Nov 11 15:59:56 2015 -0800
@@ -66,6 +66,7 @@
 import com.oracle.truffle.dsl.processor.model.SpecializationThrowsData;
 import com.oracle.truffle.dsl.processor.model.TemplateMethod;
 import com.oracle.truffle.dsl.processor.model.TypeSystemData;
+
 import java.lang.annotation.Annotation;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -79,6 +80,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
@@ -304,9 +306,7 @@
     }
 
     private List<Element> loadMembers(TypeElement templateType) {
-        List<Element> members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType));
-
-        return members;
+        return newElementList(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType));
     }
 
     private boolean containsSpecializations(List<Element> elements) {
@@ -1276,7 +1276,7 @@
 
     private static List<Element> filterNotAccessibleElements(TypeElement templateType, List<? extends Element> elements) {
         String packageName = ElementUtils.getPackageName(templateType);
-        List<Element> filteredElements = new ArrayList<>(elements);
+        List<Element> filteredElements = newElementList(elements);
         for (Element element : elements) {
             Modifier visibility = ElementUtils.getVisibility(element.getModifiers());
             if (visibility == Modifier.PRIVATE) {
@@ -1599,6 +1599,15 @@
         }
     }
 
+    /**
+     * @see "https://bugs.openjdk.java.net/browse/JDK-8039214"
+     */
+    @SuppressWarnings("unused")
+    private static List<Element> newElementList(List<? extends Element> src) {
+        List<Element> workaround = new ArrayList<Element>(src);
+        return workaround;
+    }
+
     private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
         if (!nodeData.needsFactory()) {
             // missing abstract methods only needs to be implemented
@@ -1606,7 +1615,7 @@
             return;
         }
 
-        List<Element> elements = new ArrayList<>(originalElements);
+        List<Element> elements = newElementList(originalElements);
         Set<Element> unusedElements = new HashSet<>(elements);
         for (ExecutableElement method : nodeData.getAllTemplateMethods()) {
             unusedElements.remove(method);
--- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Wed Nov 11 15:59:56 2015 -0800
@@ -32,6 +32,7 @@
 import com.oracle.truffle.dsl.processor.model.TypeCastData;
 import com.oracle.truffle.dsl.processor.model.TypeCheckData;
 import com.oracle.truffle.dsl.processor.model.TypeSystemData;
+
 import java.lang.annotation.Annotation;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -40,6 +41,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
@@ -60,6 +62,15 @@
         return TypeSystem.class;
     }
 
+    /**
+     * @see "https://bugs.openjdk.java.net/browse/JDK-8039214"
+     */
+    @SuppressWarnings("unused")
+    private static List<Element> newElementList(List<? extends Element> src) {
+        List<Element> workaround = new ArrayList<Element>(src);
+        return workaround;
+    }
+
     @Override
     protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
         TypeElement templateType = (TypeElement) element;
@@ -94,7 +105,7 @@
 
         verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
 
-        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
+        List<Element> elements = newElementList(context.getEnvironment().getElementUtils().getAllMembers(templateType));
         List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
         List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
         List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java	Wed Nov 11 15:59:56 2015 -0800
@@ -22,20 +22,74 @@
  */
 package com.oracle.truffle.object;
 
-import com.oracle.truffle.object.debug.JSONShapeVisitor;
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
+import java.nio.file.Paths;
 import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
+import com.oracle.truffle.api.nodes.GraphPrintVisitor;
+import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.api.object.Property;
+import com.oracle.truffle.object.debug.GraphvizShapeVisitor;
+import com.oracle.truffle.object.debug.IGVShapeVisitor;
+import com.oracle.truffle.object.debug.JSONShapeVisitor;
+import com.oracle.truffle.object.debug.ShapeProfiler;
+
 class Debug {
     private static Collection<ShapeImpl> allShapes;
 
-    static void registerShape(ShapeImpl newShape) {
+    static void trackShape(ShapeImpl newShape) {
         allShapes.add(newShape);
     }
 
+    static void trackObject(DynamicObject obj) {
+        ShapeProfiler.getInstance().track(obj);
+    }
+
+    static Iterable<ShapeImpl> getAllShapes() {
+        return allShapes;
+    }
+
+    static String dumpObject(DynamicObject object, int level, int levelStop) {
+        List<Property> properties = object.getShape().getPropertyListInternal(true);
+        StringBuilder sb = new StringBuilder(properties.size() * 10);
+        sb.append("{\n");
+        for (Property property : properties) {
+            indent(sb, level + 1);
+
+            sb.append(property.getKey());
+            sb.append('[').append(property.getLocation()).append(']');
+            Object value = property.get(object, false);
+            if (value instanceof DynamicObject) {
+                if (level < levelStop) {
+                    value = dumpObject((DynamicObject) value, level + 1, levelStop);
+                } else {
+                    value = value.toString();
+                }
+            }
+            sb.append(": ");
+            sb.append(value);
+            if (property != properties.get(properties.size() - 1)) {
+                sb.append(",");
+            }
+            sb.append("\n");
+        }
+        indent(sb, level);
+        sb.append("}");
+        return sb.toString();
+    }
+
+    private static StringBuilder indent(StringBuilder sb, int level) {
+        for (int i = 0; i < level; i++) {
+            sb.append(' ');
+        }
+        return sb;
+    }
+
     static {
         if (ObjectStorageOptions.DumpShapes) {
             allShapes = new ConcurrentLinkedQueue<>();
@@ -44,10 +98,36 @@
         if (ObjectStorageOptions.DumpShapes) {
             Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                 public void run() {
-                    try (PrintWriter out = new PrintWriter("shapes.json", "UTF-8")) {
+                    try {
+                        if (ObjectStorageOptions.DumpShapesDOT) {
+                            dumpDOT();
+                        }
+                        if (ObjectStorageOptions.DumpShapesJSON) {
+                            dumpJSON();
+                        }
+                        if (ObjectStorageOptions.DumpShapesIGV) {
+                            dumpIGV();
+                        }
+                    } catch (FileNotFoundException | UnsupportedEncodingException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+
+                private void dumpDOT() throws FileNotFoundException, UnsupportedEncodingException {
+                    try (PrintWriter out = new PrintWriter(getOutputFile("dot"), "UTF-8")) {
+                        GraphvizShapeVisitor visitor = new GraphvizShapeVisitor();
+                        for (ShapeImpl shape : getAllShapes()) {
+                            shape.accept(visitor);
+                        }
+                        out.println(visitor);
+                    }
+                }
+
+                private void dumpJSON() throws FileNotFoundException, UnsupportedEncodingException {
+                    try (PrintWriter out = new PrintWriter(getOutputFile("json"), "UTF-8")) {
                         out.println("{\"shapes\": [");
                         boolean first = true;
-                        for (ShapeImpl shape : allShapes) {
+                        for (ShapeImpl shape : getAllShapes()) {
                             if (!first) {
                                 out.println(",");
                             }
@@ -58,9 +138,37 @@
                             out.println();
                         }
                         out.println("]}");
-                    } catch (FileNotFoundException | UnsupportedEncodingException e) {
-                        throw new RuntimeException(e);
+                    }
+                }
+
+                private void dumpIGV() {
+                    GraphPrintVisitor printer = new GraphPrintVisitor();
+                    printer.beginGroup("shapes");
+                    IGVShapeVisitor visitor = new IGVShapeVisitor(printer);
+                    for (ShapeImpl shape : getAllShapes()) {
+                        if (isRootShape(shape)) {
+                            printer.beginGraph(DebugShapeVisitor.getId(shape));
+                            shape.accept(visitor);
+                            printer.endGraph();
+                        }
                     }
+                    printer.beginGraph("all shapes");
+                    for (ShapeImpl shape : getAllShapes()) {
+                        if (isRootShape(shape)) {
+                            shape.accept(visitor);
+                        }
+                    }
+                    printer.endGraph();
+                    printer.endGroup();
+                    printer.printToNetwork(false);
+                }
+
+                private boolean isRootShape(ShapeImpl shape) {
+                    return shape.getParent() == null;
+                }
+
+                private File getOutputFile(String extension) {
+                    return Paths.get(ObjectStorageOptions.DumpShapesPath, "shapes." + extension).toFile();
                 }
             }));
         }
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java	Wed Nov 11 15:59:56 2015 -0800
@@ -29,8 +29,6 @@
 import com.oracle.truffle.api.object.Property;
 import com.oracle.truffle.api.object.Shape;
 import com.oracle.truffle.object.Locations.ValueLocation;
-import com.oracle.truffle.object.debug.ShapeProfiler;
-import java.util.List;
 
 public abstract class DynamicObjectImpl extends DynamicObject implements Cloneable {
     private ShapeImpl shape;
@@ -43,7 +41,7 @@
         setShape(shape);
 
         if (ObjectStorageOptions.Profile) {
-            trackObject(this);
+            Debug.trackObject(this);
         }
     }
 
@@ -207,39 +205,7 @@
     }
 
     public String debugDump(int level, int levelStop) {
-        List<Property> properties = this.getShape().getPropertyListInternal(true);
-        StringBuilder sb = new StringBuilder(properties.size() * 10);
-        sb.append("{\n");
-        for (Property property : properties) {
-            indent(sb, level + 1);
-
-            sb.append(property.getKey());
-            sb.append('[').append(property.getLocation()).append(']');
-            Object value = property.get(this, false);
-            if (value instanceof DynamicObjectImpl) {
-                if (level < levelStop) {
-                    value = ((DynamicObjectImpl) value).debugDump(level + 1, levelStop);
-                } else {
-                    value = value.toString();
-                }
-            }
-            sb.append(": ");
-            sb.append(value);
-            if (property != properties.get(properties.size() - 1)) {
-                sb.append(",");
-            }
-            sb.append("\n");
-        }
-        indent(sb, level);
-        sb.append("}");
-        return sb.toString();
-    }
-
-    private static StringBuilder indent(StringBuilder sb, int level) {
-        for (int i = 0; i < level; i++) {
-            sb.append(' ');
-        }
-        return sb;
+        return Debug.dumpObject(this, level, levelStop);
     }
 
     @Override
@@ -333,10 +299,6 @@
         return getShape().getLayout().getStrategy().updateShape(this);
     }
 
-    private static void trackObject(DynamicObject obj) {
-        ShapeProfiler.getInstance().track(obj);
-    }
-
     @Override
     public final DynamicObject copy(Shape currentShape) {
         return cloneWithShape(currentShape);
@@ -344,6 +306,6 @@
 
     @Override
     public ForeignAccess getForeignAccess() {
-        return getShape().getForeignAccessFactory();
+        return getShape().getForeignAccessFactory(this);
     }
 }
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java	Wed Nov 11 15:59:56 2015 -0800
@@ -40,7 +40,11 @@
     // Debug options (should be final)
     public static final boolean DebugCounters = booleanOption(OPTION_PREFIX + "DebugCounters", true);
     public static final boolean TraceReshape = booleanOption(OPTION_PREFIX + "TraceReshape", false);
-    public static final boolean DumpShapes = booleanOption(OPTION_PREFIX + "DumpShapes", false);
+    public static final boolean DumpShapesDOT = booleanOption(OPTION_PREFIX + "DumpShapesDOT", false);
+    public static final boolean DumpShapesJSON = booleanOption(OPTION_PREFIX + "DumpShapesJSON", false);
+    public static final boolean DumpShapesIGV = booleanOption(OPTION_PREFIX + "DumpShapesIGV", false);
+    public static final boolean DumpShapes = DumpShapesDOT || DumpShapesJSON || DumpShapesIGV;
+    public static final String DumpShapesPath = System.getProperty(OPTION_PREFIX + "DumpShapesPath", "");
 
     public static final boolean Profile = booleanOption(OPTION_PREFIX + "Profile", false);
     public static final int ProfileTopResults = Integer.getInteger(OPTION_PREFIX + "ProfileTopResults", -1);
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Wed Nov 11 15:59:56 2015 -0800
@@ -154,7 +154,9 @@
         this.extraData = objectType.createShapeData(this);
 
         shapeCount.inc();
-        debugRegisterShape(this);
+        if (ObjectStorageOptions.DumpShapes) {
+            Debug.trackShape(this);
+        }
     }
 
     protected ShapeImpl(Layout layout, ShapeImpl parent, ObjectType operations, Object sharedData, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) {
@@ -1126,12 +1128,6 @@
         }
     }
 
-    private static void debugRegisterShape(ShapeImpl newShape) {
-        if (ObjectStorageOptions.DumpShapes) {
-            Debug.registerShape(newShape);
-        }
-    }
-
     /**
      * Match all filter.
      */
@@ -1152,7 +1148,7 @@
     private static final DebugCounter shapeCacheHitCount = DebugCounter.create("Shape cache hits");
     private static final DebugCounter shapeCacheMissCount = DebugCounter.create("Shape cache misses");
 
-    public ForeignAccess getForeignAccessFactory() {
-        return getObjectType().getForeignAccessFactory();
+    public ForeignAccess getForeignAccessFactory(DynamicObject object) {
+        return getObjectType().getForeignAccessFactory(object);
     }
 }
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java	Wed Nov 11 15:59:56 2015 -0800
@@ -42,7 +42,7 @@
     @Override
     public GraphvizShapeVisitor visitShape(Shape shape, Map<? extends Transition, ? extends Shape> transitions) {
         if (!drawn.add(shape)) {
-            return null;
+            return this;
         }
 
         String prefix = "s";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/IGVShapeVisitor.java	Wed Nov 11 15:59:56 2015 -0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ * 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.object.debug;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.oracle.truffle.api.nodes.GraphPrintVisitor;
+import com.oracle.truffle.api.nodes.GraphPrintVisitor.GraphPrintAdapter;
+import com.oracle.truffle.api.nodes.GraphPrintVisitor.GraphPrintHandler;
+import com.oracle.truffle.api.object.Shape;
+import com.oracle.truffle.object.DebugShapeVisitor;
+import com.oracle.truffle.object.ShapeImpl;
+import com.oracle.truffle.object.Transition;
+
+public class IGVShapeVisitor extends DebugShapeVisitor<IGVShapeVisitor> {
+    private final GraphPrintVisitor graphPrinter;
+
+    public IGVShapeVisitor(GraphPrintVisitor printer) {
+        this.graphPrinter = printer;
+    }
+
+    @Override
+    public IGVShapeVisitor visitShape(final Shape shape, final Map<? extends Transition, ? extends Shape> transitions) {
+        graphPrinter.visit(shape, new GraphPrintHandler() {
+            public void visit(Object node, GraphPrintAdapter printer) {
+                if (!printer.visited(node)) {
+                    Shape s = (Shape) node;
+                    printer.createElementForNode(s);
+                    String name = s.getLastProperty() == null ? "ROOT" : s.getLastProperty().toString();
+                    printer.setNodeProperty(s, "name", name);
+                    printer.setNodeProperty(s, "valid", s.isValid());
+                    printer.setNodeProperty(s, "identityHashCode", Integer.toHexString(System.identityHashCode(s)));
+                    printer.setNodeProperty(s, "objectType", s.getObjectType());
+
+                    for (Entry<? extends Transition, ? extends Shape> entry : transitions.entrySet()) {
+                        Shape dst = entry.getValue();
+                        ((ShapeImpl) dst).accept(IGVShapeVisitor.this);
+                        assert printer.visited(dst);
+                        printer.connectNodes(s, dst, entry.getKey().getShortName());
+                    }
+                }
+            }
+        });
+
+        return this;
+    }
+}
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -50,17 +50,18 @@
 import com.oracle.truffle.api.vm.EventConsumer;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import java.io.ByteArrayOutputStream;
+import java.util.LinkedList;
 import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import org.junit.Test;
 
 public class SLDebugTest {
     private Source factorial;
     private Debugger debugger;
-    private Callable<?> run;
+    private final LinkedList<Callable<?>> run = new LinkedList<>();
     private SuspendedEvent suspendedEvent;
     private Throwable ex;
     private ExecutionEvent executionEvent;
@@ -89,7 +90,7 @@
 
         ByteArrayOutputStream os = new ByteArrayOutputStream();
 
-        PolyglotEngine engine = PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()).onEvent(new EventConsumer<ExecutionEvent>(ExecutionEvent.class) {
+        PolyglotEngine engine = PolyglotEngine.newBuilder().onEvent(new EventConsumer<ExecutionEvent>(ExecutionEvent.class) {
             @Override
             protected void on(ExecutionEvent event) {
                 onExecution(event);
@@ -101,14 +102,7 @@
             }
         }).setOut(os).build();
 
-        PolyglotEngine.Value value;
-        synchronized (this) {
-            value = engine.eval(factorial);
-            wait();
-        }
-        assertNotNull("Debugger initalized", debugger);
-
-        run(new Callable<Void>() {
+        onEvent(new Callable<Void>() {
             @Override
             public Void call() throws Exception {
                 LineLocation nMinusOne = factorial.createLineLocation(7);
@@ -118,10 +112,11 @@
             }
         });
 
+        PolyglotEngine.Value value = engine.eval(factorial);
+
         assertNull("Parsing done", value.get());
 
-        PolyglotEngine.Value main = engine.findGlobalSymbol("main");
-        value = main.invoke(null);
+        assertExecutedOK();
 
         run(new Callable<Void>() {
             @Override
@@ -172,67 +167,62 @@
             }
         });
 
-        run(null);
+        PolyglotEngine.Value main = engine.findGlobalSymbol("main");
+        value = main.invoke(null);
+
+        assertExecutedOK();
 
         Number n = value.as(Number.class);
         assertNotNull(n);
         assertEquals("Factorial computed OK", 2, n.intValue());
     }
 
-    synchronized void onExecution(ExecutionEvent event) {
+    void onExecution(ExecutionEvent event) {
         executionEvent = event;
         debugger = event.getDebugger();
-        notifyAll();
-        waitForWork();
+        performWork();
     }
 
-    synchronized void onSuspended(SuspendedEvent event) {
+    void onSuspended(SuspendedEvent event) {
         suspendedEvent = event;
-        notifyAll();
-        waitForWork();
+        performWork();
     }
 
-    private synchronized void run(Callable<?> callable) throws Throwable {
+    private void run(Callable<?> callable) throws Throwable {
         if (ex != null) {
             throw ex;
         }
-        while (run != null) {
-            wait();
+        if (callable == null) {
+            assertTrue("Assuming all requests processed: " + run, run.isEmpty());
+            return;
         }
-        run = callable;
-        notifyAll();
+        run.addLast(callable);
         if (ex != null) {
             throw ex;
         }
     }
 
-    private void waitForWork() {
+    private void performWork() {
+        Callable<?> c = run.removeFirst();
         try {
-            waitForWork0().call();
-        } catch (Throwable tmpEx) {
-            this.ex = tmpEx;
+            c.call();
+        } catch (Exception e) {
+            this.ex = e;
         }
-
     }
 
-    private synchronized Callable<?> waitForWork0() {
-        while (run == null) {
-            try {
-                wait();
-            } catch (InterruptedException tmpEx) {
-                throw new IllegalStateException(tmpEx);
-            }
-        }
-        Callable<?> c = run;
-        run = null;
-        notifyAll();
-        return c;
+    private void assertExecutedOK() throws Throwable {
+        run(null);
     }
 
-    void assertLine(int line) {
+    private void assertLine(int line) {
         assertNotNull(suspendedEvent);
         final SourceSection expLoc = factorial.createSection("Line " + line, line);
         final SourceSection sourceLoc = suspendedEvent.getNode().getEncapsulatingSourceSection();
         assertEquals("Exp\n" + expLoc + "\nbut was\n" + sourceLoc, line, sourceLoc.getLineLocation().getLineNumber());
     }
+
+    private void onEvent(Callable<Void> callable) throws Throwable {
+        run(callable);
+    }
 }
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLJavaInteropTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLJavaInteropTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -74,7 +74,7 @@
         String scriptText = "function main() {\n" + "    println(\"Called!\");\n" + "}\n";
         Source script = Source.fromText(scriptText, "Test").withMimeType("application/x-sl");
         ByteArrayOutputStream os = new ByteArrayOutputStream();
-        PolyglotEngine engine = PolyglotEngine.buildNew().setOut(os).build();
+        PolyglotEngine engine = PolyglotEngine.newBuilder().setOut(os).build();
         engine.eval(script);
         PolyglotEngine.Value main = engine.findGlobalSymbol("main");
         final Object value = main.get();
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -69,13 +69,13 @@
 
     @Test
     public void testVerifyPresence() {
-        PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         assertTrue("Our language is present", vm.getLanguages().containsKey("application/x-sl"));
     }
 
     @Override
     protected PolyglotEngine prepareVM() throws Exception {
-        PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         // @formatter:off
         vm.eval(
             Source.fromText(
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Wed Nov 11 15:59:56 2015 -0800
@@ -286,7 +286,7 @@
 
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         try {
-            PolyglotEngine vm = PolyglotEngine.buildNew().setIn(new ByteArrayInputStream(repeat(testCase.testInput, repeats).getBytes("UTF-8"))).setOut(out).build();
+            PolyglotEngine vm = PolyglotEngine.newBuilder().setIn(new ByteArrayInputStream(repeat(testCase.testInput, repeats).getBytes("UTF-8"))).setOut(out).build();
 
             String script = readAllLines(testCase.path);
 
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ToStringOfEvalTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ToStringOfEvalTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -52,7 +52,7 @@
 
     @Test
     public void checkToStringOnAFunction() throws IOException {
-        PolyglotEngine engine = PolyglotEngine.buildNew().build();
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
         PolyglotEngine.Language sl = engine.getLanguages().get("application/x-sl");
         sl.eval(Source.fromText("function checkName() {}", "defineFn"));
         PolyglotEngine.Value value1 = engine.findGlobalSymbol("checkName");
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/InstrumentationTestMode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/InstrumentationTestMode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -52,7 +52,7 @@
     public static void set(boolean enable) {
 
         try {
-            final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+            final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
             final Field instrumenterField = vm.getClass().getDeclaredField("instrumenter");
             instrumenterField.setAccessible(true);
             final Object instrumenter = instrumenterField.get(vm);
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Wed Nov 11 15:59:56 2015 -0800
@@ -240,7 +240,7 @@
             // We use the name of the file to determine what visitor to attach to it.
             if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) {
                 // Set up the execution context for Simple and register our two listeners
-                PolyglotEngine vm = PolyglotEngine.buildNew().setIn(new ByteArrayInputStream(testCase.testInput.getBytes("UTF-8"))).setOut(out).build();
+                PolyglotEngine vm = PolyglotEngine.newBuilder().setIn(new ByteArrayInputStream(testCase.testInput.getBytes("UTF-8"))).setOut(out).build();
 
                 final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
                 field.setAccessible(true);
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Wed Nov 11 15:59:56 2015 -0800
@@ -50,6 +50,7 @@
 import java.util.List;
 
 import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
@@ -185,7 +186,7 @@
  */
 
 /*
- *
+ * 
  * <p> <b>Tools:</b><br> The use of some of Truffle's support for developer tools (based on the
  * Truffle {@linkplain Instrumenter Instrumentation Framework}) are demonstrated in this file, for
  * example: <ul> <li>a {@linkplain NodeExecCounter counter for node executions}, tabulated by node
@@ -226,7 +227,7 @@
      * The main entry point. Use the mx command "mx sl" to run it with the correct class path setup.
      */
     public static void main(String[] args) throws IOException {
-        PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         assert vm.getLanguages().containsKey("application/x-sl");
 
         setupToolDemos();
@@ -254,21 +255,6 @@
     }
 
     /**
-     * Temporary method during API evolution, supports debugger integration.
-     */
-    @Deprecated
-    public static void run(Source source) throws IOException {
-        PolyglotEngine vm = PolyglotEngine.buildNew().build();
-        assert vm.getLanguages().containsKey("application/x-sl");
-        vm.eval(source);
-        Value main = vm.findGlobalSymbol("main");
-        if (main == null) {
-            throw new SLException("No function main() defined in SL source file.");
-        }
-        main.invoke(null);
-    }
-
-    /**
      * Parse and run the specified SL source. Factored out in a separate method so that it can also
      * be used by the unit test harness.
      */
@@ -434,6 +420,7 @@
             failed[0] = e;
         }
         return new CallTarget() {
+            @TruffleBoundary
             @Override
             public Object call(Object... arguments) {
                 if (failed[0] instanceof RuntimeException) {
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java	Wed Nov 11 15:59:56 2015 -0800
@@ -58,7 +58,7 @@
  * generated ones would not be sufficient.
  */
 @TypeSystem({long.class, BigInteger.class, boolean.class, String.class, SLFunction.class, SLNull.class})
-@DSLOptions(useNewLayout = true)
+@DSLOptions
 public abstract class SLTypes {
 
     /**
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -73,11 +73,10 @@
      * We use a separate long specialization to avoid boxing for long.
      */
     @Specialization(limit = "CACHE_LIMIT", guards = {"longLocation != null", "shape.check(receiver)"}, assumptions = "shape.getValidAssumption()")
-    @SuppressWarnings("unused")
     protected long doCachedLong(DynamicObject receiver,   //
                     @Cached("receiver.getShape()") Shape shape,   //
                     @Cached("getLongLocation(shape)") LongLocation longLocation) {
-        return longLocation.getLong(receiver, true);
+        return longLocation.getLong(receiver, shape);
     }
 
     protected LongLocation getLongLocation(Shape shape) {
@@ -108,27 +107,14 @@
      */
     @Specialization(contains = "doCachedObject")
     @TruffleBoundary
-    protected Object doGeneric(DynamicObject receiver, @Cached("new()") LRUPropertyLookup lruCache) {
-        if (!lruCache.shape.check(receiver)) {
-            Shape receiverShape = receiver.getShape();
-            lruCache.shape = receiverShape;
-            lruCache.property = receiverShape.getProperty(propertyName);
-        }
-        if (lruCache.property != null) {
-            return lruCache.property.get(receiver, true);
+    protected Object doGeneric(DynamicObject receiver) {
+        Shape shape = receiver.getShape();
+        Property property = shape.getProperty(propertyName);
+        if (property != null) {
+            return property.get(receiver, shape);
         } else {
             return SLNull.SINGLETON;
         }
     }
 
-    protected static class LRUPropertyLookup {
-
-        private Shape shape;
-        private Property property;
-
-        public LRUPropertyLookup() {
-        }
-
-    }
-
 }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java	Wed Nov 11 15:59:56 2015 -0800
@@ -42,9 +42,9 @@
 
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.object.FinalLocationException;
@@ -52,8 +52,11 @@
 import com.oracle.truffle.api.object.Location;
 import com.oracle.truffle.api.object.Property;
 import com.oracle.truffle.api.object.Shape;
+import com.oracle.truffle.api.utilities.AlwaysValidAssumption;
+import com.oracle.truffle.api.utilities.NeverValidAssumption;
 
 public abstract class SLWritePropertyCacheNode extends Node {
+    protected static final int CACHE_LIMIT = 3;
 
     protected final String propertyName;
 
@@ -63,105 +66,78 @@
 
     public abstract void executeObject(DynamicObject receiver, Object value);
 
-    @Specialization(guards = "location.isValid(receiver, value)", assumptions = "location.getAssumptions()")
-    public void writeCached(DynamicObject receiver, Object value,   //
-                    @Cached("createCachedWrite(receiver, value)") CachedWriteLocation location) {
-        if (location.writeUnchecked(receiver, value)) {
-            // write successful
-        } else {
+    @Specialization(guards = {"location != null", "shape.check(receiver)", "canSet(location, receiver, value)"}, assumptions = {"shape.getValidAssumption()"}, limit = "CACHE_LIMIT")
+    public void writeExistingPropertyCached(DynamicObject receiver, Object value, //
+                    @Cached("lookupLocation(receiver, value)") Location location, //
+                    @Cached("receiver.getShape()") Shape shape, //
+                    @Cached("ensureValid(receiver)") Assumption validAssumption) {
+        try {
+            validAssumption.check();
+        } catch (InvalidAssumptionException e) {
             executeObject(receiver, value);
+            return;
         }
-    }
-
-    @Specialization(contains = "writeCached")
-    @TruffleBoundary
-    public void writeGeneric(DynamicObject receiver, Object value,   //
-                    @Cached("new(createCachedWrite(receiver, value))") LRUCachedWriteLocation lru) {
-        CachedWriteLocation location = lru.location;
-        if (!location.isValid(receiver, value) || !location.areAssumptionsValid()) {
-            location = createCachedWrite(receiver, value);
-            lru.location = location;
-        }
-        if (location.writeUnchecked(receiver, value)) {
-            // write successful
-        } else {
-            executeObject(receiver, value);
+        try {
+            location.set(receiver, value, shape);
+        } catch (IncompatibleLocationException | FinalLocationException e) {
+            throw new IllegalStateException(e);
         }
     }
 
-    protected CachedWriteLocation createCachedWrite(DynamicObject receiver, Object value) {
-        while (receiver.updateShape()) {
-            // multiple shape updates might be needed.
-        }
-
-        Shape oldShape = receiver.getShape();
-        Shape newShape;
-        Property property = oldShape.getProperty(propertyName);
-
-        if (property != null && property.getLocation().canSet(receiver, value)) {
-            newShape = oldShape;
-        } else {
-            receiver.define(propertyName, value, 0);
-            newShape = receiver.getShape();
-            property = newShape.getProperty(propertyName);
-        }
-
-        if (!oldShape.check(receiver)) {
-            return createCachedWrite(receiver, value);
+    @Specialization(guards = {"existing == null", "shapeBefore.check(receiver)", "canSet(newLocation, receiver, value)"}, assumptions = {"shapeBefore.getValidAssumption()",
+                    "shapeAfter.getValidAssumption()"}, limit = "CACHE_LIMIT")
+    public void writeNewPropertyCached(DynamicObject receiver, Object value, //
+                    @Cached("lookupLocation(receiver, value)") @SuppressWarnings("unused") Location existing, //
+                    @Cached("receiver.getShape()") Shape shapeBefore, //
+                    @Cached("defineProperty(receiver, value)") Shape shapeAfter, //
+                    @Cached("getLocation(shapeAfter)") Location newLocation, //
+                    @Cached("ensureValid(receiver)") Assumption validAssumption) {
+        try {
+            validAssumption.check();
+        } catch (InvalidAssumptionException e) {
+            executeObject(receiver, value);
+            return;
         }
-
-        return new CachedWriteLocation(oldShape, newShape, property.getLocation());
-
-    }
-
-    protected static final class CachedWriteLocation {
-
-        private final Shape oldShape;
-        private final Shape newShape;
-        private final Location location;
-        private final Assumption validLocation = Truffle.getRuntime().createAssumption();
-
-        public CachedWriteLocation(Shape oldShape, Shape newShape, Location location) {
-            this.oldShape = oldShape;
-            this.newShape = newShape;
-            this.location = location;
-        }
-
-        public boolean areAssumptionsValid() {
-            return validLocation.isValid() && oldShape.getValidAssumption().isValid() && newShape.getValidAssumption().isValid();
-        }
-
-        public Assumption[] getAssumptions() {
-            return new Assumption[]{oldShape.getValidAssumption(), newShape.getValidAssumption(), validLocation};
-        }
-
-        public boolean isValid(DynamicObject receiver, Object value) {
-            return oldShape.check(receiver) && location.canSet(receiver, value);
-        }
-
-        public boolean writeUnchecked(DynamicObject receiver, Object value) {
-            try {
-                if (oldShape == newShape) {
-                    location.set(receiver, value, oldShape);
-                } else {
-                    location.set(receiver, value, oldShape, newShape);
-                }
-                return true;
-            } catch (IncompatibleLocationException | FinalLocationException e) {
-                validLocation.invalidate();
-                return false;
-            }
+        try {
+            newLocation.set(receiver, value, shapeBefore, shapeAfter);
+        } catch (IncompatibleLocationException e) {
+            throw new IllegalStateException(e);
         }
     }
 
-    protected static final class LRUCachedWriteLocation {
+    @Specialization(contains = {"writeExistingPropertyCached", "writeNewPropertyCached"})
+    @TruffleBoundary
+    public void writeUncached(DynamicObject receiver, Object value) {
+        receiver.define(propertyName, value);
+    }
 
-        private CachedWriteLocation location;
+    protected final Location lookupLocation(DynamicObject object, Object value) {
+        final Shape oldShape = object.getShape();
+        final Property property = oldShape.getProperty(propertyName);
+
+        if (property != null && property.getLocation().canSet(object, value)) {
+            return property.getLocation();
+        } else {
+            return null;
+        }
+    }
 
-        public LRUCachedWriteLocation(CachedWriteLocation location) {
-            this.location = location;
-        }
+    protected final Shape defineProperty(DynamicObject receiver, Object value) {
+        Shape oldShape = receiver.getShape();
+        Shape newShape = oldShape.defineProperty(propertyName, value, 0);
+        return newShape;
+    }
 
+    protected final Location getLocation(Shape newShape) {
+        return newShape.getProperty(propertyName).getLocation();
+    }
+
+    protected static Assumption ensureValid(DynamicObject receiver) {
+        return receiver.updateShape() ? NeverValidAssumption.INSTANCE : AlwaysValidAssumption.INSTANCE;
+    }
+
+    protected static boolean canSet(Location location, DynamicObject receiver, Object value) {
+        return location.canSet(receiver, value);
     }
 
 }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLObjectType.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLObjectType.java	Wed Nov 11 15:59:56 2015 -0800
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public ForeignAccess getForeignAccessFactory() {
+    public ForeignAccess getForeignAccessFactory(DynamicObject obj) {
         return access;
     }
 
--- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java	Wed Nov 11 15:59:56 2015 -0800
@@ -134,7 +134,7 @@
                 }
             }
         };
-        engine = PolyglotEngine.buildNew().onEvent(onHalted).onEvent(onExec).build();
+        engine = PolyglotEngine.newBuilder().onEvent(onHalted).onEvent(onExec).build();
         this.language = engine.getLanguages().get(mimeType);
         if (language == null) {
             throw new RuntimeException("Implementation not found for \"" + mimeType + "\"");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java	Wed Nov 11 15:59:56 2015 -0800
@@ -0,0 +1,144 @@
+/*
+ * 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.tools.debug.shell.server;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.oracle.truffle.api.debug.Breakpoint;
+import com.oracle.truffle.api.debug.Debugger;
+import com.oracle.truffle.api.debug.SuspendedEvent;
+import com.oracle.truffle.api.frame.FrameInstance;
+import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.instrument.Visualizer;
+import com.oracle.truffle.api.instrument.impl.DefaultVisualizer;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.api.vm.PolyglotEngine.Language;
+import com.oracle.truffle.tools.debug.shell.REPLMessage;
+
+public abstract class REPLServerContext {
+
+    private final int level;
+    private final SuspendedEvent event;
+
+    protected REPLServerContext(int level, SuspendedEvent event) {
+        this.level = level;
+        this.event = event;
+    }
+
+    /**
+     * The nesting depth of this context in the current session.
+     */
+    public int getLevel() {
+        return level;
+    }
+
+    /**
+     * The AST node where execution is halted in this context.
+     */
+    public Node getNodeAtHalt() {
+        return event.getNode();
+    }
+
+    /**
+     * Evaluates given code snippet in the context of currently suspended execution.
+     *
+     * @param code the snippet to evaluate
+     * @param frame <code>null</code> in case the evaluation should happen in top most frame,
+     *            non-null value
+     * @return result of the evaluation
+     * @throws IOException if something goes wrong
+     */
+    // public Object eval(String code, FrameInstance frame) throws IOException {
+    // return event.eval(code, frame);
+    // }
+
+    /**
+     * The frame where execution is halted in this context.
+     */
+    public MaterializedFrame getFrameAtHalt() {
+        return event.getFrame();
+    }
+
+    public abstract Language getLanguage();
+
+    public Visualizer getVisualizer() {
+        return new DefaultVisualizer();
+    }
+
+    public PolyglotEngine engine() {
+        throw new IllegalStateException();
+    }
+
+    protected abstract Debugger db();
+
+    /**
+     * Dispatches a REPL request to the appropriate handler.
+     */
+    public abstract REPLMessage[] receive(REPLMessage request);
+
+    public abstract void registerBreakpoint(Breakpoint breakpoint);
+
+    public abstract Breakpoint findBreakpoint(int id);
+
+    public abstract int getBreakpointID(Breakpoint breakpoint);
+
+    /**
+     * Provides access to the execution stack.
+     *
+     * @return immutable list of stack elements
+     */
+    public List<FrameDebugDescription> getStack() {
+        List<FrameDebugDescription> frames = new ArrayList<>();
+        int frameCount = 1;
+        for (FrameInstance frameInstance : event.getStack()) {
+            if (frameCount == 1) {
+                frames.add(new FrameDebugDescription(frameCount, event.getNode(), frameInstance));
+            } else {
+                frames.add(new FrameDebugDescription(frameCount, frameInstance.getCallNode(), frameInstance));
+            }
+            frameCount++;
+        }
+        return Collections.unmodifiableList(frames);
+    }
+
+    void prepareStepOut() {
+        event.prepareStepOut();
+    }
+
+    void prepareStepInto(int repeat) {
+        event.prepareStepInto(repeat);
+    }
+
+    void prepareStepOver(int repeat) {
+        event.prepareStepOver(repeat);
+    }
+
+    void prepareContinue() {
+        event.prepareContinue();
+    }
+}
--- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -44,7 +44,7 @@
 
     @Test
     public void testNoExecution() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
@@ -72,7 +72,7 @@
 
     @Test
     public void testCountingCoverage() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
--- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -45,7 +45,7 @@
 
     @Test
     public void testNoExecution() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
@@ -61,7 +61,7 @@
 
     @Test
     public void testMapping1() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
@@ -92,7 +92,7 @@
 
     @Test
     public void testMapping2() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
--- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -42,7 +42,7 @@
 
     @Test
     public void testNoExecution() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
@@ -76,7 +76,7 @@
 
     @Test
     public void testCounting() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
--- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java	Wed Nov 11 15:59:56 2015 -0800
@@ -123,7 +123,7 @@
     }
 
     private static Instrumenter getInstrumenter() throws NoSuchFieldException, IllegalAccessException {
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
+        final PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
--- a/truffle/overview.html	Tue Nov 10 19:42:37 2015 -0800
+++ b/truffle/overview.html	Wed Nov 11 15:59:56 2015 -0800
@@ -57,5 +57,33 @@
   <li><a target="_blank" href="http://ssw.jku.at/Research/Projects/JVM/Graal.html">Papers on Graal</a></li>
 </ul>
 
+<h4>Keeping Compatibility</h4>
+
+<p>
+The <b>Truffle</b> API values work of its adopters and as such it is developed
+with compatibility in mind. Methods and features are not removed and renamed
+randomly, without a notice and there is a binary compatibility testing framework
+in place to verify that.
+</p>
+<p>
+On the other hand the <b>Truffle</b> project is still young and needs a way
+to refine and change previously taken decisions. To balance the need between
+compatibility and give us a way to remove things from the API we following
+these rules:
+</p>
+<ul>
+    <li>Rather than removing/renaming or changing an API element (class, method,
+        field), mark it <em>deprecated</em>.</li>
+    <li>Make sure usage of such element can be replaced by non-deprecated ways</li>
+    <li>Keep such element working until next release</li>
+    <li>If possible provide automatic migration using Jackpot's META-INF/upgrade/ files</li>
+    <li>When new (major) release is out, remove it</li>
+</ul>
+<p>
+By deprecating parts of API while keeping them functional we are giving
+users of the <b>Truffle</b> API time to adjust to required
+changes and (under the assumption they pay attention to warnings in the code
+base) easily identify and migrate to more modern API alternatives.
+</p>
 </body>
 </html>