changeset 22096:1e78795e7e6a

Allow to specify globalSymbols when defining TruffleVM
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Tue, 18 Aug 2015 16:10:03 +0200
parents 0058a9461865 (diff) 643d53cb3147 (current diff)
children c6966c8ea83c
files truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/SymbolInvokerImpl.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java
diffstat 32 files changed, 432 insertions(+), 651 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/SymbolInvokerImpl.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/SymbolInvokerImpl.java	Tue Aug 18 16:10:03 2015 +0200
@@ -37,43 +37,96 @@
 public final class SymbolInvokerImpl extends SymbolInvoker {
     static final FrameDescriptor UNUSED_FRAMEDESCRIPTOR = new FrameDescriptor();
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "rawtypes"})
     @Override
-    protected Object invoke(TruffleLanguage<?> lang, Object symbol, Object... arr) throws IOException {
-        if (symbol instanceof String) {
-            return symbol;
+    protected CallTarget createCallTarget(TruffleLanguage<?> lang, Object symbol, Object... arr) throws IOException {
+        Class<? extends TruffleLanguage<?>> type;
+        if (lang != null) {
+            type = (Class) lang.getClass();
+        } else {
+            type = (Class) TruffleLanguage.class;
+        }
+        RootNode symbolNode;
+        if ((symbol instanceof String) || (symbol instanceof Number) || (symbol instanceof Boolean) || (symbol instanceof Character)) {
+            symbolNode = new ConstantRootNode(type, symbol);
+        } else {
+            Node executeMain = Message.createExecute(arr.length).createNode();
+            symbolNode = new TemporaryRoot(type, executeMain, (TruffleObject) symbol, arr.length);
         }
-        if (symbol instanceof Number) {
-            return symbol;
+        return Truffle.getRuntime().createCallTarget(symbolNode);
+    }
+
+    private final class ConstantRootNode extends RootNode {
+
+        private final Object value;
+
+        public ConstantRootNode(Class<? extends TruffleLanguage<?>> lang, Object value) {
+            super(lang, null, null);
+            this.value = value;
+        }
+
+        @Override
+        public Object execute(VirtualFrame vf) {
+            return value;
         }
-        if (symbol instanceof Boolean) {
-            return symbol;
+    }
+
+    private static class TemporaryRoot extends RootNode {
+        @Child private Node foreignAccess;
+        @Child private ConvertNode convert;
+        private final int argumentLength;
+        private final TruffleObject function;
+
+        public TemporaryRoot(Class<? extends TruffleLanguage<?>> lang, Node foreignAccess, TruffleObject function, int argumentLength) {
+            super(lang, null, null);
+            this.foreignAccess = foreignAccess;
+            this.convert = new ConvertNode();
+            this.function = function;
+            this.argumentLength = argumentLength;
         }
-        Class<? extends TruffleLanguage<?>> type = (Class<? extends TruffleLanguage<?>>) lang.getClass();
-        Node executeMain = Message.createExecute(arr.length).createNode();
-        CallTarget callTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(type, executeMain, (TruffleObject) symbol, arr));
-        VirtualFrame frame = Truffle.getRuntime().createVirtualFrame(arr, UNUSED_FRAMEDESCRIPTOR);
-        Object ret = callTarget.call(frame);
-        if (ret instanceof TruffleObject) {
-            TruffleObject tret = (TruffleObject) ret;
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            final Object[] args = frame.getArguments();
+            if (args.length != argumentLength) {
+                throw new ArgumentsMishmashException();
+            }
+            Object tmp = ForeignAccess.execute(foreignAccess, frame, function, args);
+            return convert.convert(frame, tmp);
+        }
+    }
+
+    private static final class ConvertNode extends Node {
+        @Child private Node isNull;
+        @Child private Node isBoxed;
+        @Child private Node unbox;
+
+        public ConvertNode() {
+            this.isNull = Message.IS_NULL.createNode();
+            this.isBoxed = Message.IS_BOXED.createNode();
+            this.unbox = Message.UNBOX.createNode();
+        }
+
+        Object convert(VirtualFrame frame, Object obj) {
+            if (obj instanceof TruffleObject) {
+                return convert(frame, (TruffleObject) obj);
+            } else {
+                return obj;
+            }
+        }
+
+        private Object convert(VirtualFrame frame, TruffleObject obj) {
             Object isBoxedResult;
             try {
-                Node isBoxed = Message.IS_BOXED.createNode();
-                CallTarget isBoxedTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(type, isBoxed, tret));
-                isBoxedResult = isBoxedTarget.call(frame);
+                isBoxedResult = ForeignAccess.execute(isBoxed, frame, obj);
             } catch (IllegalArgumentException ex) {
                 isBoxedResult = false;
             }
             if (Boolean.TRUE.equals(isBoxedResult)) {
-                Node unbox = Message.UNBOX.createNode();
-                CallTarget unboxTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(type, unbox, tret));
-                Object unboxResult = unboxTarget.call(frame);
-                return unboxResult;
+                return ForeignAccess.execute(unbox, frame, obj);
             } else {
                 try {
-                    Node isNull = Message.IS_NULL.createNode();
-                    CallTarget isNullTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(type, isNull, tret));
-                    Object isNullResult = isNullTarget.call(frame);
+                    Object isNullResult = ForeignAccess.execute(isNull, frame, obj);
                     if (Boolean.TRUE.equals(isNullResult)) {
                         return null;
                     }
@@ -81,26 +134,7 @@
                     // fallthrough
                 }
             }
-        }
-        return ret;
-    }
-
-    private static class TemporaryRoot extends RootNode {
-        @Child private Node foreignAccess;
-        private final TruffleObject function;
-        private final Object[] args;
-
-        public TemporaryRoot(Class<? extends TruffleLanguage<?>> lang, Node foreignAccess, TruffleObject function, Object... args) {
-            super(lang, null, null);
-            this.foreignAccess = foreignAccess;
-            this.function = function;
-            this.args = args;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return ForeignAccess.execute(foreignAccess, frame, function, args);
+            return obj;
         }
     }
-
 }
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DebugCounter.java	Thu Aug 13 10:27:30 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, 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.object;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.atomic.*;
-
-public final class DebugCounter {
-    private static final ArrayList<DebugCounter> allCounters = new ArrayList<>();
-
-    private final String name;
-    private final AtomicLong value;
-
-    private DebugCounter(String name) {
-        this.name = name;
-        this.value = new AtomicLong();
-        allCounters.add(this);
-    }
-
-    public static DebugCounter create(String name) {
-        return new DebugCounter(name);
-    }
-
-    public long get() {
-        return value.get();
-    }
-
-    public void inc() {
-        value.incrementAndGet();
-    }
-
-    @Override
-    public String toString() {
-        return name + ": " + value;
-    }
-
-    public static void dumpCounters() {
-        dumpCounters(System.out);
-    }
-
-    public static void dumpCounters(PrintStream out) {
-        for (DebugCounter counter : allCounters) {
-            out.println(counter);
-        }
-    }
-}
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java	Tue Aug 18 16:10:03 2015 +0200
@@ -27,6 +27,11 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.interop.*;
 
+/**
+ * Represents an object members of which can be dynamically added and removed at run time.
+ *
+ * @see Shape
+ */
 public abstract class DynamicObject implements TypedObject, TruffleObject {
     /**
      * Get the object's current shape.
@@ -37,6 +42,16 @@
      * Get property value.
      *
      * @param key property identifier
+     * @return property value or {@code null} if object has no such property
+     */
+    public final Object get(Object key) {
+        return get(key, null);
+    }
+
+    /**
+     * Get property value.
+     *
+     * @param key property identifier
      * @param defaultValue return value if property is not found
      * @return property value or defaultValue if object has no such property
      */
@@ -146,6 +161,19 @@
      */
     public abstract boolean updateShape();
 
+    /**
+     * Create a shallow copy of this object.
+     *
+     * @param currentShape the object's current shape (must equal {@link #getShape()})
+     */
+    public abstract DynamicObject copy(Shape currentShape);
+
+    /**
+     * Represents an operation on a single {@code int}-valued operand that produces an {@code int}
+     * -valued result.
+     *
+     * For Java 7 compatibility (equivalent to IntUnaryOperator).
+     */
     public interface FlagsFunction {
         int apply(int t);
     }
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/FinalLocationException.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/FinalLocationException.java	Tue Aug 18 16:10:03 2015 +0200
@@ -26,6 +26,9 @@
 
 import com.oracle.truffle.api.nodes.*;
 
+/**
+ * This exception is thrown on an attempt to assign a value to a final location.
+ */
 public final class FinalLocationException extends SlowPathException {
     private static final long serialVersionUID = -30188494510914293L;
 }
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/HiddenKey.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/HiddenKey.java	Tue Aug 18 16:10:03 2015 +0200
@@ -24,6 +24,10 @@
  */
 package com.oracle.truffle.api.object;
 
+/**
+ * A unique key to be used for private object fields; excluded from enumeration and compared by
+ * object identity.
+ */
 public final class HiddenKey {
     private final String name;
 
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IncompatibleLocationException.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IncompatibleLocationException.java	Tue Aug 18 16:10:03 2015 +0200
@@ -26,6 +26,9 @@
 
 import com.oracle.truffle.api.nodes.*;
 
+/**
+ * This exception is thrown on an attempt to assign an incompatible value to a location.
+ */
 public final class IncompatibleLocationException extends SlowPathException {
     private static final long serialVersionUID = -7734865392357341789L;
 }
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java	Tue Aug 18 16:10:03 2015 +0200
@@ -29,6 +29,11 @@
 import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
 import com.oracle.truffle.api.object.Shape.Allocator;
 
+/**
+ * Describes layout and behavior of a {@link DynamicObject} subclass and is used to create shapes.
+ *
+ * An object may change its shape but only to shapes of the same layout.
+ */
 public abstract class Layout {
     public static final EnumSet<ImplicitCast> NONE = EnumSet.noneOf(ImplicitCast.class);
     public static final EnumSet<ImplicitCast> INT_TO_DOUBLE = EnumSet.of(ImplicitCast.IntToDouble);
@@ -38,6 +43,9 @@
 
     private static final LayoutFactory LAYOUT_FACTORY = loadLayoutFactory();
 
+    /**
+     * Specifies the allowed implicit casts between primitive types without losing type information.
+     */
     public enum ImplicitCast {
         IntToDouble,
         IntToLong,
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutBuilder.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutBuilder.java	Tue Aug 18 16:10:03 2015 +0200
@@ -29,6 +29,11 @@
 import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
 import com.oracle.truffle.api.object.Layout.ImplicitCast;
 
+/**
+ * Layout builder.
+ *
+ * @see Layout
+ */
 public class LayoutBuilder {
     private EnumSet<ImplicitCast> allowedImplicitCasts;
     private FieldOffsetProvider fieldOffsetProvider;
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationModifier.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationModifier.java	Tue Aug 18 16:10:03 2015 +0200
@@ -24,7 +24,17 @@
  */
 package com.oracle.truffle.api.object;
 
+/**
+ * Location modifiers specify the desired semantics and allowed use of a location to be allocated by
+ * {@link Shape.Allocator}.
+ */
 public enum LocationModifier {
+    /**
+     * Location is going to be set only during object initialization.
+     */
     Final,
+    /**
+     * Location is never set to {@code null} and initialized before it is read.
+     */
     NonNull,
 }
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java	Tue Aug 18 16:10:03 2015 +0200
@@ -249,10 +249,6 @@
 
     public abstract Shape tryMerge(Shape other);
 
-    public <R> R accept(ShapeVisitor<R> visitor) {
-        return visitor.visitShape(this);
-    }
-
     public abstract static class Allocator {
         protected abstract Location locationForValue(Object value, boolean useFinal, boolean nonNull);
 
@@ -280,10 +276,17 @@
         public abstract Location declaredLocation(Object value);
 
         public abstract Allocator addLocation(Location location);
+
+        /**
+         * Creates an copy of this allocator.
+         */
+        public abstract Allocator copy();
     }
 
     /**
-     * Represents a predicate (boolean-valued function) of one argument. For Java 7 compatibility.
+     * Represents a predicate (boolean-valued function) of one argument.
+     *
+     * For Java 7 compatibility (equivalent to Predicate).
      *
      * @param <T> the type of the input to the predicate
      */
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeVisitor.java	Thu Aug 13 10:27:30 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, 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.object;
-
-public interface ShapeVisitor<R> {
-    R visitShape(Shape shape);
-}
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/TypedLocation.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/TypedLocation.java	Tue Aug 18 16:10:03 2015 +0200
@@ -24,6 +24,9 @@
  */
 package com.oracle.truffle.api.object;
 
+/**
+ * A location that can store a value of a particular type.
+ */
 public interface TypedLocation extends BaseLocation {
     /**
      * The type of this location.
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTagTest.java	Thu Aug 13 10:27:30 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * 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.
- *
- * 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.test.source;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.source.*;
-
-public class SourceTagTest {
-
-    @Test
-    public void sourceTagTest() {
-
-        // Private tag
-        final SourceTag testTag = new SourceTag() {
-
-            public String name() {
-                return null;
-            }
-
-            public String getDescription() {
-                return null;
-            }
-        };
-
-        // No sources exist with the private tag
-        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 0);
-
-        // Create a new source
-        final Source source = Source.fromText("test1 source", "test1 source");
-
-        // Initially has only the default tag
-        assertEquals(source.getSourceTags().size(), 1);
-
-        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
-        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
-        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
-
-        assertFalse(source.isTaggedAs(testTag));
-        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 0);
-
-        // Add a private tag
-        source.tagAs(testTag);
-
-        // Now there are exactly two tags
-        assertEquals(source.getSourceTags().size(), 2);
-
-        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
-        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
-        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
-
-        assertTrue(source.getSourceTags().contains(testTag));
-        assertTrue(source.isTaggedAs(testTag));
-        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 1);
-        assertTrue(Source.findSourcesTaggedAs(testTag).contains(source));
-
-        // Add the private tag again
-        source.tagAs(testTag);
-
-        // Nothing has changed
-        assertEquals(source.getSourceTags().size(), 2);
-
-        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
-        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
-        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
-
-        assertTrue(source.getSourceTags().contains(testTag));
-        assertTrue(source.isTaggedAs(testTag));
-        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 1);
-        assertTrue(Source.findSourcesTaggedAs(testTag).contains(source));
-    }
-
-    @Test
-    public void sourceListenerTest() {
-
-        // Private tag
-        final SourceTag testTag = new SourceTag() {
-
-            public String name() {
-                return null;
-            }
-
-            public String getDescription() {
-                return null;
-            }
-        };
-
-        final int[] newSourceEvents = {0};
-        final Source[] newSource = {null};
-
-        final int[] newTagEvents = {0};
-        final Source[] taggedSource = {null};
-        final SourceTag[] newTag = {null};
-
-        Source.addSourceListener(new SourceListener() {
-
-            public void sourceCreated(Source source) {
-                newSourceEvents[0] = newSourceEvents[0] + 1;
-                newSource[0] = source;
-            }
-
-            public void sourceTaggedAs(Source source, SourceTag tag) {
-                newTagEvents[0] = newTagEvents[0] + 1;
-                taggedSource[0] = source;
-                newTag[0] = tag;
-            }
-        });
-
-        // New source has a default tag applied.
-        // Get one event for the new source, another one when it gets tagged
-        final Source source = Source.fromText("testSource", "testSource");
-        assertEquals(newSourceEvents[0], 1);
-        assertEquals(newSource[0], source);
-        assertEquals(newTagEvents[0], 1);
-        assertEquals(taggedSource[0], source);
-        assertEquals(newTag[0], Source.Tags.FROM_LITERAL);
-
-        // reset
-        newSource[0] = null;
-        taggedSource[0] = null;
-        newTag[0] = null;
-
-        // Add a tag; only get one event (the new tag)
-        source.tagAs(testTag);
-        assertEquals(newSourceEvents[0], 1);
-        assertEquals(newSource[0], null);
-        assertEquals(newTagEvents[0], 2);
-        assertEquals(taggedSource[0], source);
-        assertEquals(newTag[0], testTag);
-
-        // Add the same tag; no events, and nothing changes.
-        source.tagAs(testTag);
-        assertEquals(newSourceEvents[0], 1);
-        assertEquals(newSource[0], null);
-        assertEquals(newTagEvents[0], 2);
-        assertEquals(taggedSource[0], source);
-        assertEquals(newTag[0], testTag);
-
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java	Tue Aug 18 16:10:03 2015 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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.api.test.vm;
+
+import com.oracle.truffle.api.impl.Accessor;
+import static com.oracle.truffle.api.test.vm.ImplicitExplicitExportTest.L1;
+import com.oracle.truffle.api.vm.TruffleVM;
+import java.io.IOException;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+public class ExceptionDuringParsingTest {
+    public static Accessor API;
+
+    @Test
+    public void canGetAccessToOwnLanguageInstance() throws Exception {
+        TruffleVM vm = TruffleVM.newVM().build();
+        TruffleVM.Language language = vm.getLanguages().get(L1);
+        assertNotNull("L1 language is defined", language);
+
+        try {
+            vm.eval(L1, "parse=No, no, no!");
+            fail("Exception thrown");
+        } catch (IOException ex) {
+            assertEquals(ex.getMessage(), "No, no, no!");
+        }
+    }
+}
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Tue Aug 18 16:10:03 2015 +0200
@@ -128,6 +128,9 @@
 
         @Override
         protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
+            if (code.getCode().startsWith("parse=")) {
+                throw new IOException(code.getCode().substring(6));
+            }
             return new ValueCallTarget(code, this);
         }
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Tue Aug 18 16:10:03 2015 +0200
@@ -39,12 +39,12 @@
 import java.util.WeakHashMap;
 
 /**
- * An entry point for everyone who wants to implement a Truffle based language. By providing
+ * An entry point for everyone who wants to implement a Truffle based language. By providing an
  * implementation of this type and registering it using {@link Registration} annotation, your
  * language becomes accessible to users of the {@link TruffleVM Truffle virtual machine} - all they
- * will need to do is to include your JAR into their application and all the Truffle goodies (multi
- * language support, multitenant hosting, debugging, etc.) will be made available to them.
- * 
+ * will need to do is to include your JAR into their application and all the Truffle goodies
+ * (multi-language support, multitenant hosting, debugging, etc.) will be made available to them.
+ *
  * @param <C> internal state of the language associated with every thread that is executing program
  *            {@link #parse(com.oracle.truffle.api.source.Source, com.oracle.truffle.api.nodes.Node, java.lang.String...)
  *            parsed} by the language
@@ -99,7 +99,7 @@
      * <em>execution</em>. The returned execution context is completely language specific; it is
      * however expected it will contain reference to here-in provided <code>env</code> and adjust
      * itself according to parameters provided by the <code>env</code> object.
-     * 
+     *
      * @param env the environment the language is supposed to operate in
      * @return internal data of the language in given environment
      */
@@ -120,7 +120,9 @@
      *            {@link CallTarget#call(java.lang.Object...)}
      * @return a call target to invoke which also keeps in memory the {@link Node} tree representing
      *         just parsed <code>code</code>
-     * @throws IOException thrown when I/O or parsing goes wrong
+     * @throws IOException thrown when I/O or parsing goes wrong. Here-in thrown exception is
+     *             propagate to the user who called one of <code>eval</code> methods of
+     *             {@link TruffleVM}
      */
     protected abstract CallTarget parse(Source code, Node context, String... argumentNames) throws IOException;
 
@@ -177,7 +179,7 @@
      * Allows a language implementor to create a node that can effectively lookup up the context
      * associated with current execution. The context is created by
      * {@link #createContext(com.oracle.truffle.api.TruffleLanguage.Env)} method.
-     * 
+     *
      * @return node to be inserted into program to effectively find out current execution context
      *         for this language
      */
@@ -189,7 +191,7 @@
 
     /**
      * Uses the {@link #createFindContextNode()} node to obtain the current context.
-     * 
+     *
      * @param n the node created by this language's {@link #createFindContextNode()}
      * @return the context created by
      *         {@link #createContext(com.oracle.truffle.api.TruffleLanguage.Env)} method at the
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ExecutionEvent.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ExecutionEvent.java	Tue Aug 18 16:10:03 2015 +0200
@@ -34,8 +34,8 @@
  * place to initialize debugger - e.g. set
  * {@link Debugger#setLineBreakpoint(int, com.oracle.truffle.api.source.LineLocation, boolean)
  * breakpoints} or specify to execution should halt on the {@link #prepareStepInto() first possible
- * occurence}. Methods in this event can only be used while the handlers process the event. Then the
- * state of the event becomes invalid and subsequent calls to the event methods yield
+ * occurrence}. Methods in this event can only be used while the handlers process the event. Then
+ * the state of the event becomes invalid and subsequent calls to the event methods yield
  * {@link IllegalStateException}. One can however obtain reference to {@link Debugger} instance and
  * keep it to further manipulate with debugging capabilities of the {@link TruffleVM} when it is
  * running.
@@ -48,7 +48,7 @@
     }
 
     /**
-     * Debugger associated with the execution. This debuger remains valid after the event is
+     * Debugger associated with the execution. This debugger remains valid after the event is
      * processed, it is possible and suggested to keep a reference to it and use it any time later
      * when evaluating sources in the {@link TruffleVM}.
      *
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Tue Aug 18 16:10:03 2015 +0200
@@ -155,9 +155,9 @@
         return API.getDebugSupport(l);
     }
 
-    protected Object invoke(TruffleLanguage<?> lang, Object obj, Object[] args) throws IOException {
+    protected CallTarget createCallTarget(TruffleLanguage<?> lang, Object obj, Object[] args) throws IOException {
         for (SymbolInvoker si : ServiceLoader.load(SymbolInvoker.class)) {
-            return si.invoke(lang, obj, args);
+            return si.createCallTarget(lang, obj, args);
         }
         throw new IOException("No symbol invoker found!");
     }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java	Tue Aug 18 16:10:03 2015 +0200
@@ -24,6 +24,7 @@
  */
 package com.oracle.truffle.api.impl;
 
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.TruffleLanguage;
 import java.io.*;
 
@@ -32,5 +33,17 @@
  * associated nodes too much.
  */
 public abstract class SymbolInvoker {
-    protected abstract Object invoke(TruffleLanguage<?> lang, Object symbol, Object... args) throws IOException;
+    protected abstract CallTarget createCallTarget(TruffleLanguage<?> lang, Object symbol, Object... args) throws IOException;
+
+    public static final class ArgumentsMishmashException extends IllegalArgumentException {
+        static final long serialVersionUID = 1L;
+
+        public ArgumentsMishmashException() {
+        }
+
+        @Override
+        public synchronized Throwable fillInStackTrace() {
+            return this;
+        }
+    }
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Aug 18 16:10:03 2015 +0200
@@ -179,7 +179,7 @@
         adoptHelper();
     }
 
-    private void adoptHelper(final Node newChild) {
+    void adoptHelper(final Node newChild) {
         assert newChild != null;
         if (newChild == this) {
             throw new IllegalStateException("The parent of a node can never be the node itself.");
@@ -280,9 +280,7 @@
         // (aw) need to set parent *before* replace, so that (unsynchronized) getRootNode()
         // will always find the root node
         newNode.parent = this.parent;
-        if (NodeUtil.replaceChild(this.parent, this, newNode)) {
-            this.parent.adoptHelper(newNode);
-        } else {
+        if (!NodeUtil.replaceChild(this.parent, this, newNode, true)) {
             this.parent.adoptUnadoptedHelper(newNode);
         }
         reportReplace(this, newNode, reason);
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Tue Aug 18 16:10:03 2015 +0200
@@ -199,12 +199,19 @@
     }
 
     public static boolean replaceChild(Node parent, Node oldChild, Node newChild) {
+        return replaceChild(parent, oldChild, newChild, false);
+    }
+
+    static boolean replaceChild(Node parent, Node oldChild, Node newChild, boolean adopt) {
         CompilerAsserts.neverPartOfCompilation();
         NodeClass nodeClass = parent.getNodeClass();
 
         for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) {
             if (nodeField.getObject(parent) == oldChild) {
                 assert assertAssignable(nodeField, newChild);
+                if (adopt) {
+                    parent.adoptHelper(newChild);
+                }
                 nodeField.putObject(parent, newChild);
                 return true;
             }
@@ -217,6 +224,9 @@
                 for (int i = 0; i < array.length; i++) {
                     if (array[i] == oldChild) {
                         assert assertAssignable(nodeField, newChild);
+                        if (adopt) {
+                            parent.adoptHelper(newChild);
+                        }
                         array[i] = newChild;
                         return true;
                     }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java	Tue Aug 18 16:10:03 2015 +0200
@@ -26,8 +26,10 @@
 
 import javax.script.*;
 
+@Deprecated
 /**
  * Tool access to the creation of Truffle execution engines.
+ * @deprecated no longer needed and will be removed
  */
 public abstract class TruffleScriptEngineFactory implements ScriptEngineFactory {
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Tue Aug 18 16:10:03 2015 +0200
@@ -27,15 +27,11 @@
 import java.io.*;
 import java.lang.ref.*;
 import java.net.*;
+import java.nio.*;
+import java.nio.charset.*;
 import java.util.*;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.instrument.*;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
 
 /**
  * Representation of a guest language source code unit and its contents. Sources originate in
@@ -89,65 +85,12 @@
  * reload.</li>
  * </ol>
  * <p>
- *
- * @see SourceTag
- * @see SourceListener
  */
 public abstract class Source {
 
     // TODO (mlvdv) consider canonicalizing and reusing SourceSection instances
     // TOOD (mlvdv) connect SourceSections into a spatial tree for fast geometric lookup
 
-    public enum Tags implements SourceTag {
-
-        /**
-         * From bytes.
-         */
-        FROM_BYTES("bytes", "read from bytes"),
-
-        /**
-         * Read from a file.
-         */
-        FROM_FILE("file", "read from a file"),
-
-        /**
-         * From literal text.
-         */
-        FROM_LITERAL("literal", "from literal text"),
-
-        /**
-         * From a {@linkplain java.io.Reader Reader}.
-         */
-        FROM_READER("reader", "read from a Java Reader"),
-
-        /**
-         * Read from a URL.
-         */
-        FROM_URL("URL", "read from a URL");
-
-        private final String name;
-        private final String description;
-
-        private Tags(String name, String description) {
-            this.name = name;
-            this.description = description;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-
-    }
-
-    /**
-     * All Sources that have been created.
-     */
-    private static final List<WeakReference<Source>> allSources = Collections.synchronizedList(new ArrayList<WeakReference<Source>>());
-
     /**
      * Index of all named sources.
      */
@@ -155,8 +98,6 @@
 
     private static boolean fileCacheEnabled = true;
 
-    private static final List<SourceListener> sourceListeners = new ArrayList<>();
-
     /**
      * Locates an existing instance by the name under which it was indexed.
      */
@@ -194,7 +135,6 @@
         if (reset) {
             source.reset();
         }
-        notifyNewSource(source).tagAs(Tags.FROM_FILE);
         return source;
     }
 
@@ -237,7 +177,6 @@
                 nameToSource.put(path, new WeakReference<>(source));
             }
         }
-        notifyNewSource(source).tagAs(Tags.FROM_FILE);
         return source;
     }
 
@@ -250,11 +189,8 @@
      */
     public static Source fromText(CharSequence chars, String description) {
         CompilerAsserts.neverPartOfCompilation();
-
         assert chars != null;
-        final LiteralSource source = new LiteralSource(description, chars.toString());
-        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
-        return source;
+        return new LiteralSource(description, chars.toString());
     }
 
     /**
@@ -266,10 +202,7 @@
      */
     public static Source fromAppendableText(String description) {
         CompilerAsserts.neverPartOfCompilation();
-
-        final Source source = new AppendableLiteralSource(description);
-        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
-        return source;
+        return new AppendableLiteralSource(description);
     }
 
     /**
@@ -283,10 +216,8 @@
      */
     public static Source fromNamedText(CharSequence chars, String name) {
         CompilerAsserts.neverPartOfCompilation();
-
         final Source source = new LiteralSource(name, chars.toString());
         nameToSource.put(name, new WeakReference<>(source));
-        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
         return source;
     }
 
@@ -301,10 +232,8 @@
      */
     public static Source fromNamedAppendableText(String name) {
         CompilerAsserts.neverPartOfCompilation();
-
         final Source source = new AppendableLiteralSource(name);
         nameToSource.put(name, new WeakReference<>(source));
-        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
         return source;
     }
 
@@ -320,7 +249,6 @@
      */
     public static Source subSource(Source base, int baseCharIndex, int length) {
         CompilerAsserts.neverPartOfCompilation();
-
         final SubSource subSource = SubSource.create(base, baseCharIndex, length);
         return subSource;
     }
@@ -350,10 +278,7 @@
      */
     public static Source fromURL(URL url, String description) throws IOException {
         CompilerAsserts.neverPartOfCompilation();
-
-        final URLSource source = URLSource.get(url, description);
-        notifyNewSource(source).tagAs(Tags.FROM_URL);
-        return source;
+        return URLSource.get(url, description);
     }
 
     /**
@@ -366,10 +291,7 @@
      */
     public static Source fromReader(Reader reader, String description) throws IOException {
         CompilerAsserts.neverPartOfCompilation();
-
-        final LiteralSource source = new LiteralSource(description, read(reader));
-        notifyNewSource(source).tagAs(Tags.FROM_READER);
-        return source;
+        return new LiteralSource(description, read(reader));
     }
 
     /**
@@ -401,10 +323,7 @@
      */
     public static Source fromBytes(byte[] bytes, int byteIndex, int length, String description, Charset charset) {
         CompilerAsserts.neverPartOfCompilation();
-
-        final BytesSource source = new BytesSource(description, bytes, byteIndex, length, charset);
-        notifyNewSource(source).tagAs(Tags.FROM_BYTES);
-        return source;
+        return new BytesSource(description, bytes, byteIndex, length, charset);
     }
 
     // TODO (mlvdv) enable per-file choice whether to cache?
@@ -416,50 +335,6 @@
         fileCacheEnabled = enabled;
     }
 
-    /**
-     * Returns all {@link Source}s holding a particular {@link SyntaxTag}, or the whole collection
-     * of Sources if the specified tag is {@code null}.
-     *
-     * @return A collection of Sources containing the given tag.
-     */
-    public static Collection<Source> findSourcesTaggedAs(SourceTag tag) {
-        final List<Source> taggedSources = new ArrayList<>();
-        synchronized (allSources) {
-            for (WeakReference<Source> ref : allSources) {
-                Source source = ref.get();
-                if (source != null) {
-                    if (tag == null || source.isTaggedAs(tag)) {
-                        taggedSources.add(ref.get());
-                    }
-                }
-            }
-        }
-        return taggedSources;
-    }
-
-    /**
-     * Adds a {@link SourceListener} to receive events.
-     */
-    public static void addSourceListener(SourceListener listener) {
-        assert listener != null;
-        sourceListeners.add(listener);
-    }
-
-    /**
-     * Removes a {@link SourceListener}. Ignored if listener not found.
-     */
-    public static void removeSourceListener(SourceListener listener) {
-        sourceListeners.remove(listener);
-    }
-
-    private static Source notifyNewSource(Source source) {
-        allSources.add(new WeakReference<>(source));
-        for (SourceListener listener : sourceListeners) {
-            listener.sourceCreated(source);
-        }
-        return source;
-    }
-
     private static String read(Reader reader) throws IOException {
         final BufferedReader bufferedReader = new BufferedReader(reader);
         final StringBuilder builder = new StringBuilder();
@@ -479,8 +354,6 @@
         return builder.toString();
     }
 
-    private final ArrayList<SourceTag> tags = new ArrayList<>();
-
     private Source() {
     }
 
@@ -488,32 +361,6 @@
 
     abstract void reset();
 
-    public final boolean isTaggedAs(SourceTag tag) {
-        assert tag != null;
-        return tags.contains(tag);
-    }
-
-    public final Collection<SourceTag> getSourceTags() {
-        return Collections.unmodifiableCollection(tags);
-    }
-
-    /**
-     * Adds a {@linkplain SourceTag tag} to the set of tags associated with this {@link Source};
-     * {@code no-op} if already in the set.
-     *
-     * @return this
-     */
-    public final Source tagAs(SourceTag tag) {
-        assert tag != null;
-        if (!tags.contains(tag)) {
-            tags.add(tag);
-            for (SourceListener listener : sourceListeners) {
-                listener.sourceTaggedAs(this, tag);
-            }
-        }
-        return this;
-    }
-
     /**
      * Returns the name of this resource holding a guest language program. An example would be the
      * name of a guest language source code file.
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceListener.java	Thu Aug 13 10:27:30 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-/**
- * An observer of events related to {@link Source}s: creating and tagging.
- */
-public interface SourceListener {
-
-    /**
-     * Notifies that a new {@link Source} has just been created.
-     */
-    void sourceCreated(Source source);
-
-    /**
-     * Notifies that a {@link SourceTag} has been newly added to the set of tags associated with a
-     * {@link Source} via {@link Source#tagAs(SourceTag)}.
-     * <p>
-     * The {@linkplain SourceTag tags} at a {@link Source} are a <em>set</em>; this notification
-     * will only be delivered the first time a particular {@linkplain SourceTag tag} is added at a
-     * {@link Source}.
-     *
-     * @param source where a tag has been added
-     * @param tag the tag that has been newly added (subsequent additions of the tag are
-     *            unreported).
-     */
-    void sourceTaggedAs(Source source, SourceTag tag);
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceTag.java	Thu Aug 13 10:27:30 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-/**
- * Categorical information (best implemented as enums} about particular sources of Guest Language
- * code that can be useful to configure behavior of both the language runtime and external tools.
- * These might include {@linkplain Source.Tags standard tags} noting, for example, whether the
- * source was read from a file and whether it should be considered library code.
- * <p>
- * The need for additional tags is likely to arise, in some cases because of issue specific to a
- * Guest Language, but also for help configuring the behavior of particular tools.
- *
- * @see Source
- * @see Source.Tags
- */
-public interface SourceTag {
-
-    /**
-     * Human-friendly name of a category of code sources, e.g. "file", or "library".
-     *
-     */
-    String name();
-
-    /**
-     * Criteria and example uses for the tag.
-     */
-    String getDescription();
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java	Tue Aug 18 16:10:03 2015 +0200
@@ -39,10 +39,25 @@
 import com.oracle.truffle.api.source.*;
 
 /**
- * Virtual machine for Truffle based languages. Use {@link #newVM()} to create new isolated virtual
- * machine ready for execution of various languages. All the languages in a single virtual machine
- * see each other exported global symbols and can cooperate. Use {@link #newVM()} multiple times to
- * create different, isolated virtual machines completely separated from each other.
+ * <em>Virtual machine</em> for Truffle based languages. Term virtual machine is a bit overloaded,
+ * so don't think of <em>Java virtual machine</em> here - while we are running and using
+ * {@link TruffleVM} inside of a <em>JVM</em> there can be multiple instances (some would say
+ * tenants) of {@link TruffleVM} running next to each other in a single <em>JVM</em> with a complete
+ * mutual isolation. There is 1:N mapping between <em>JVM</em> and {@link TruffleVM}.
+ * <p>
+ * It would not be correct to think of a {@link TruffleVM} as a runtime for a single Truffle
+ * language (Ruby, Python, R, C, JavaScript, etc.) either. {@link TruffleVM} can host as many of
+ * Truffle languages as {@link Registration registered on a class path} of your <em>JVM</em>
+ * application. {@link TruffleVM} orchestrates these languages, manages exchange of objects and
+ * calls among them. While it may happen that there is just one activated language inside of a
+ * {@link TruffleVM}, the greatest strength of {@link TruffleVM} is in interoperability between all
+ * Truffle languages. There is 1:N mapping between {@link TruffleVM} and {@link TruffleLanguage
+ * Truffle language implementations}.
+ * <p>
+ * Use {@link #newVM()} to create new isolated virtual machine ready for execution of various
+ * languages. All the languages in a single virtual machine see each other exported global symbols
+ * and can cooperate. Use {@link #newVM()} multiple times to create different, isolated virtual
+ * machines 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)}.
@@ -52,7 +67,8 @@
  * <p>
  * The <code>TruffleVM</code> 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 thread.
+ * the same thread. There is 1:1 mapping between {@link TruffleVM} and a thread that can tell it
+ * what to do.
  */
 @SuppressWarnings("rawtypes")
 public final class TruffleVM {
@@ -234,10 +250,9 @@
         /**
          * Adds global named symbol into the configuration of to-be-built {@link TruffleVM}. This
          * symbol will be accessible to all languages via {@link Env#importSymbol(java.lang.String)}
-         * and will take precedence over
-         * {@link TruffleLanguage#findExportedSymbol(java.lang.Object, java.lang.String, boolean)
-         * symbols exported by languages itself}. Repeated use of <code>globalSymbol</code> is
-         * possible; later definition of the same name overrides the previous one.
+         * and will take precedence over {@link TruffleLanguage#findExportedSymbol symbols exported
+         * by languages itself}. Repeated use of <code>globalSymbol</code> is possible; later
+         * definition of the same name overrides the previous one.
          * 
          * @param name name of the symbol to register
          * @param obj value of the object - expected to be primitive wrapper, {@link String} or
@@ -462,6 +477,7 @@
         private final TruffleLanguage<?> language;
         private final Object obj;
         private final Object global;
+        private CallTarget target;
 
         Symbol(TruffleLanguage<?> language, Object obj, Object global) {
             this.language = language;
@@ -482,6 +498,7 @@
          * @throws IOException signals problem during execution
          */
         public Object invoke(Object thiz, Object... args) throws IOException {
+            checkThread();
             Debugger[] fillIn = {debugger};
             try (Closeable c = SPI.executionStart(TruffleVM.this, fillIn, null)) {
                 if (debugger == null) {
@@ -496,7 +513,16 @@
                     arr.add(thiz);
                 }
                 arr.addAll(Arrays.asList(args));
-                return SPI.invoke(language, obj, arr.toArray());
+                for (;;) {
+                    if (target == null) {
+                        target = SPI.createCallTarget(language, obj, arr.toArray());
+                    }
+                    try {
+                        return target.call(arr.toArray());
+                    } catch (SymbolInvoker.ArgumentsMishmashException ex) {
+                        target = null;
+                    }
+                }
             }
         }
     }
@@ -671,8 +697,8 @@
         }
 
         @Override
-        protected Object invoke(TruffleLanguage<?> lang, Object obj, Object[] args) throws IOException {
-            return super.invoke(lang, obj, args);
+        protected CallTarget createCallTarget(TruffleLanguage<?> lang, Object obj, Object[] args) throws IOException {
+            return super.createCallTarget(lang, obj, args);
         }
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DebugCounter.java	Tue Aug 18 16:10:03 2015 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 2014, 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;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+public final class DebugCounter {
+    private static final ArrayList<DebugCounter> allCounters = new ArrayList<>();
+
+    private final String name;
+    private final AtomicLong value;
+
+    private DebugCounter(String name) {
+        this.name = name;
+        this.value = new AtomicLong();
+        allCounters.add(this);
+    }
+
+    public static DebugCounter create(String name) {
+        return new DebugCounter(name);
+    }
+
+    public long get() {
+        return value.get();
+    }
+
+    public void inc() {
+        value.incrementAndGet();
+    }
+
+    @Override
+    public String toString() {
+        return name + ": " + value;
+    }
+
+    public static void dumpCounters() {
+        dumpCounters(System.out);
+    }
+
+    public static void dumpCounters(PrintStream out) {
+        for (DebugCounter counter : allCounters) {
+            out.println(counter);
+        }
+    }
+}
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java	Tue Aug 18 16:10:03 2015 +0200
@@ -375,6 +375,11 @@
     }
 
     @Override
+    public final DynamicObject copy(Shape currentShape) {
+        return cloneWithShape(currentShape);
+    }
+
+    @Override
     public ForeignAccess getForeignAccess() {
         return getShape().getForeignAccessFactory();
     }
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Tue Aug 18 16:10:03 2015 +0200
@@ -888,6 +888,7 @@
             @ExplodeLoop
             public DynamicObject newInstance(Object... initialValues) {
                 DynamicObject store = ShapeImpl.this.newInstance();
+                CompilerAsserts.partialEvaluationConstant(instanceFields.length);
                 for (int i = 0; i < instanceFields.length; i++) {
                     instanceFields[i].setInternal(store, initialValues[i]);
                 }
@@ -910,7 +911,11 @@
         return null;
     }
 
-    public abstract static class BaseAllocator extends Allocator implements LocationVisitor {
+    public <R> R accept(ShapeVisitor<R> visitor) {
+        return visitor.visitShape(this);
+    }
+
+    public abstract static class BaseAllocator extends Allocator implements LocationVisitor, Cloneable {
         protected final LayoutImpl layout;
         protected int objectArraySize;
         protected int objectFieldSize;
@@ -1046,6 +1051,20 @@
         public void visitPrimitiveField(int index, int count) {
             primitiveFieldSize = Math.max(primitiveFieldSize, index + count);
         }
+
+        @Override
+        public final BaseAllocator copy() {
+            return clone();
+        }
+
+        @Override
+        protected final BaseAllocator clone() {
+            try {
+                return (BaseAllocator) super.clone();
+            } catch (CloneNotSupportedException e) {
+                throw new AssertionError(e);
+            }
+        }
     }
 
     private static void debugRegisterShape(ShapeImpl newShape) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeVisitor.java	Tue Aug 18 16:10:03 2015 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2014, 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;
+
+import com.oracle.truffle.api.object.*;
+
+public interface ShapeVisitor<R> {
+    R visitShape(Shape shape);
+}
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java	Tue Aug 18 16:10:03 2015 +0200
@@ -59,7 +59,7 @@
 
         for (Entry<? extends Transition, ? extends Shape> entry : transitions.entrySet()) {
             Shape dst = entry.getValue();
-            dst.accept(this);
+            ((ShapeImpl) dst).accept(this);
             assert drawn.contains(dst);
 
             sb.append(prefix).append(getId(shape)).append("->").append(prefix).append(getId(dst));
--- a/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java	Thu Aug 13 10:27:30 2015 +0200
+++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java	Tue Aug 18 16:10:03 2015 +0200
@@ -40,9 +40,6 @@
  * is specified, {@linkplain StandardSyntaxTag#STATEMENT STATEMENT} is used, corresponding to
  * conventional behavior for code coverage tools.
  * <p>
- * No counts will be kept for execution in sources that hold the {@link SourceTag}
- * {@link Tags#NO_COVERAGE}.
- * <p>
  * <b>Tool Life Cycle</b>
  * <p>
  * See {@link InstrumentationTool} for the life cycle common to all such tools.
@@ -73,30 +70,6 @@
  */
 public final class CoverageTracker extends InstrumentationTool {
 
-    public enum Tags implements SourceTag {
-
-        /**
-         * Report no counts for sources holding this tag.
-         */
-        NO_COVERAGE("No Coverage", "Coverage Tracker will igore");
-
-        private final String name;
-        private final String description;
-
-        private Tags(String name, String description) {
-            this.name = name;
-            this.description = description;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-    }
-
     /** Counting data. */
     private final Map<LineLocation, CoverageRecord> coverageMap = new HashMap<>();
 
@@ -291,28 +264,28 @@
                 final SourceSection srcSection = probe.getProbedSourceSection();
                 if (srcSection == null) {
                     // TODO (mlvdv) report this?
-                } else if (!srcSection.getSource().isTaggedAs(Tags.NO_COVERAGE)) {
-                    // Get the source line where the
-                    final LineLocation lineLocation = srcSection.getLineLocation();
-                    CoverageRecord record = coverageMap.get(lineLocation);
-                    if (record != null) {
-                        // Another node starts on same line; count only the first (textually)
-                        if (srcSection.getCharIndex() > record.srcSection.getCharIndex()) {
-                            // Existing record, corresponds to code earlier on line
-                            return;
-                        } else {
-                            // Existing record, corresponds to code at a later position; replace it
-                            record.instrument.dispose();
-                        }
+                    return;
+                }
+                // Get the source line where the
+                final LineLocation lineLocation = srcSection.getLineLocation();
+                CoverageRecord record = coverageMap.get(lineLocation);
+                if (record != null) {
+                    // Another node starts on same line; count only the first (textually)
+                    if (srcSection.getCharIndex() > record.srcSection.getCharIndex()) {
+                        // Existing record, corresponds to code earlier on line
+                        return;
+                    } else {
+                        // Existing record, corresponds to code at a later position; replace it
+                        record.instrument.dispose();
                     }
+                }
 
-                    final CoverageRecord coverage = new CoverageRecord(srcSection);
-                    final Instrument instrument = Instrument.create(coverage, CoverageTracker.class.getSimpleName());
-                    coverage.instrument = instrument;
-                    instruments.add(instrument);
-                    probe.attach(instrument);
-                    coverageMap.put(lineLocation, coverage);
-                }
+                final CoverageRecord coverage = new CoverageRecord(srcSection);
+                final Instrument instrument = Instrument.create(coverage, CoverageTracker.class.getSimpleName());
+                coverage.instrument = instrument;
+                instruments.add(instrument);
+                probe.attach(instrument);
+                coverageMap.put(lineLocation, coverage);
             }
         }
     }