# HG changeset patch # User Jaroslav Tulach # Date 1439907003 -7200 # Node ID 1e78795e7e6a1a0c6a931ddae794a97470b2610e # Parent 0058a946186563a5dccb7e425b910156ee1fe131# Parent 643d53cb3147a5e6d07360d179c123103388bef5 Allow to specify globalSymbols when defining TruffleVM diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/SymbolInvokerImpl.java --- 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> 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> 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> 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> type = (Class>) 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> 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; } } - } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DebugCounter.java --- 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 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); - } - } -} diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java --- 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); } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/FinalLocationException.java --- 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; } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/HiddenKey.java --- 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; diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IncompatibleLocationException.java --- 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; } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java --- 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 NONE = EnumSet.noneOf(ImplicitCast.class); public static final EnumSet 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, diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutBuilder.java --- 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 allowedImplicitCasts; private FieldOffsetProvider fieldOffsetProvider; diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationModifier.java --- 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, } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java --- 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 accept(ShapeVisitor 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 the type of the input to the predicate */ diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeVisitor.java --- 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 visitShape(Shape shape); -} diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/TypedLocation.java --- 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. diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTagTest.java --- 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); - - } -} diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java --- /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!"); + } + } +} diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java --- 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); } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java --- 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 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 @@ * execution. The returned execution context is completely language specific; it is * however expected it will contain reference to here-in provided env and adjust * itself according to parameters provided by the env 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 - * @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 eval 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 diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ExecutionEvent.java --- 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}. * diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java --- 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!"); } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java --- 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; + } + } } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- 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); diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- 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; } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java --- 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 { diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java --- 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. * *

- * - * @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> allSources = Collections.synchronizedList(new ArrayList>()); - /** * Index of all named sources. */ @@ -155,8 +98,6 @@ private static boolean fileCacheEnabled = true; - private static final List 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 findSourcesTaggedAs(SourceTag tag) { - final List taggedSources = new ArrayList<>(); - synchronized (allSources) { - for (WeakReference 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 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 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. diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceListener.java --- 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)}. - *

- * The {@linkplain SourceTag tags} at a {@link Source} are a set; 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); - -} diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceTag.java --- 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. - *

- * 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(); -} diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java --- 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. + * Virtual machine for Truffle based languages. Term virtual machine is a bit overloaded, + * so don't think of Java virtual machine here - while we are running and using + * {@link TruffleVM} inside of a JVM there can be multiple instances (some would say + * tenants) of {@link TruffleVM} running next to each other in a single JVM with a complete + * mutual isolation. There is 1:N mapping between JVM and {@link TruffleVM}. + *

+ * 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 JVM + * 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}. + *

+ * 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. *

* 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 @@ *

* The TruffleVM 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 globalSymbol 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 globalSymbol 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 diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DebugCounter.java --- /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 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); + } + } +} diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java --- 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(); } diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java --- 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 accept(ShapeVisitor 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) { diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeVisitor.java --- /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 visitShape(Shape shape); +} diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java --- 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 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)); diff -r 643d53cb3147 -r 1e78795e7e6a truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java --- 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. *

- * No counts will be kept for execution in sources that hold the {@link SourceTag} - * {@link Tags#NO_COVERAGE}. - *

* Tool Life Cycle *

* 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 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); } } }