# HG changeset patch # User Michael Van De Vanter # Date 1447286396 28800 # Node ID 163fdf64587ddbd596e5f85a805c9a3369a343a9 # Parent ad180d3d4bd780475281d43c47ab0c125bea4646# Parent a647534602a6b70deb64b9d96c2798d7e36e1e0e Merge with a647534602a6b70deb64b9d96c2798d7e36e1e0e diff -r ad180d3d4bd7 -r 163fdf64587d .hgtags --- a/.hgtags Tue Nov 10 19:42:37 2015 -0800 +++ b/.hgtags Wed Nov 11 15:59:56 2015 -0800 @@ -618,3 +618,4 @@ 7aab14a2bb4e5c06b2fb252753a4beca184eec5f graal-0.8 7aab14a2bb4e5c06b2fb252753a4beca184eec5f truffle-0.8 +5ee16f4908e565c39fc6d8422fda53c677d350a7 truffle-0.9 diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java --- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -42,6 +42,7 @@ import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheFieldFactory; import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheMethodFactory; import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheNodeFieldFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCachesOrderFactory; import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithCachedAndDynamicParameterFactory; import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithJustCachedParameterFactory; import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestMultipleCachesFactory; @@ -309,6 +310,35 @@ } @NodeChild + static class TestCachesOrder extends ValueNode { + + @Specialization(guards = "boundByGuard != 0") + static int do1(int value, // + @Cached("get(value)") int intermediateValue, // + @Cached("transform(intermediateValue)") int boundByGuard, // + @Cached("new()") Object notBoundByGuards) { + return intermediateValue; + } + + protected int get(int i) { + return i * 2; + } + + protected int transform(int i) { + return i * 3; + } + + } + + @Test + public void testCachesOrder() { + CallTarget root = createCallTarget(TestCachesOrderFactory.getInstance()); + assertEquals(42, root.call(21)); + assertEquals(42, root.call(22)); + assertEquals(42, root.call(23)); + } + + @NodeChild static class CachedError1 extends ValueNode { @Specialization static int do1(int value, @ExpectError("Incompatible return type int. The expression type must be equal to the parameter type double.")// diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java --- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -39,7 +39,7 @@ + "execute(VirtualFrame)' and must not throw any checked exceptions."; @TypeSystem({int.class}) - @DSLOptions(useNewLayout = true) + @DSLOptions static class ExecuteMethodTypes { } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java --- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -162,7 +162,7 @@ static int fallthrough1; static int fallthrough2; - @Specialization(order = 1, rewriteOn = ArithmeticException.class) + @Specialization(rewriteOn = ArithmeticException.class) int do1(int a) throws ArithmeticException { if (a == 0) { fallthrough1++; @@ -171,7 +171,7 @@ return a; } - @Specialization(order = 2, rewriteOn = ArithmeticException.class) + @Specialization(rewriteOn = ArithmeticException.class) int do2(int a) throws ArithmeticException { if (a == 1) { fallthrough2++; @@ -266,7 +266,7 @@ static int fallthrough1; static int fallthrough2; - @Specialization(order = 1, rewriteOn = ArithmeticException.class) + @Specialization(rewriteOn = ArithmeticException.class) int do1(int a) throws ArithmeticException { if (a == 0) { fallthrough1++; @@ -275,7 +275,7 @@ return a; } - @Specialization(order = 2, rewriteOn = ArithmeticException.class) + @Specialization(rewriteOn = ArithmeticException.class) int do2(int a) throws ArithmeticException { if (a == 1) { fallthrough2++; diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java --- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -43,7 +43,7 @@ @TypeSystem({byte.class, short.class, int.class, long.class, double.class, boolean.class, BigInteger.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Interface.class, Object[].class}) - @DSLOptions(useNewLayout = true) + @DSLOptions static class SimpleTypes { static int intCheck; diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/utilities/InstrumentationTestMode.java --- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/utilities/InstrumentationTestMode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/utilities/InstrumentationTestMode.java Wed Nov 11 15:59:56 2015 -0800 @@ -34,7 +34,7 @@ public static void set(boolean enable) { try { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field instrumenterField = vm.getClass().getDeclaredField("instrumenter"); instrumenterField.setAccessible(true); final Object instrumenter = instrumenterField.get(vm); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java --- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java Tue Nov 10 19:42:37 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.dsl; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Experimental API. - * - * @deprecated annotation has no effect anymore. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -@Deprecated -public @interface Implies { - - String[] value(); - -} diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java --- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java Tue Nov 10 19:42:37 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.dsl; - -import com.oracle.truffle.api.Assumption; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @deprecated use {@link NodeField} with type {@link Assumption} instead. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -@Deprecated -public @interface NodeAssumptions { - - String[] value(); - -} diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java --- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Wed Nov 11 15:59:56 2015 -0800 @@ -119,18 +119,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Specialization { - - /** - * @deprecated do not use anymore. Will get removed in the next release. - */ - @Deprecated int DEFAULT_ORDER = -1; - - /** - * @deprecated use declaration order instead. Will get removed in the next release. - */ - @Deprecated - int order() default DEFAULT_ORDER; - /** * References a specialization of a super class by its method name where this specialization is * inserted before. The declaration order of a specialization is not usable for nodes where diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java --- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java Wed Nov 11 15:59:56 2015 -0800 @@ -36,11 +36,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface DSLOptions { - - /** Flag has no effect anymore. Is going to be removed soon. */ - @Deprecated - boolean useNewLayout() default true; - /** * Lazy class loading ensures that all generated specialization classes are loaded lazily. * Disabling this feature will eagerly load all classes but will also reduce the generated code diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/InstrumentationTestMode.java --- a/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/InstrumentationTestMode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/InstrumentationTestMode.java Wed Nov 11 15:59:56 2015 -0800 @@ -36,7 +36,7 @@ public static void set(boolean enable) { try { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field instrumenterField = vm.getClass().getDeclaredField("instrumenter"); instrumenterField.setAccessible(true); final Object instrumenter = instrumenterField.get(vm); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/JavaFunctionTest.java --- a/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/JavaFunctionTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/JavaFunctionTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -35,7 +35,7 @@ public void invokeRunnable() throws IOException { final boolean[] called = {false}; - PolyglotEngine engine = PolyglotEngine.buildNew().globalSymbol("test", JavaInterop.asTruffleFunction(Runnable.class, new Runnable() { + PolyglotEngine engine = PolyglotEngine.newBuilder().globalSymbol("test", JavaInterop.asTruffleFunction(Runnable.class, new Runnable() { @Override public void run() { called[0] = true; diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java --- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java Wed Nov 11 15:59:56 2015 -0800 @@ -32,6 +32,8 @@ @Child private ObjectAccessNode next; private final ForeignAccess languageCheck; + @Child private ForeignAccessArguments accessArguments = new ForeignAccessArguments(); + protected CachedObjectAccessNode(DirectCallNode callTarget, ObjectAccessNode next, ForeignAccess languageCheck) { this.callTarget = callTarget; this.next = next; @@ -50,7 +52,7 @@ private Object doAccess(VirtualFrame frame, TruffleObject receiver, Object[] arguments) { if (languageCheck.canHandle(receiver)) { - return callTarget.call(frame, ForeignAccessArguments.create(receiver, arguments)); + return callTarget.call(frame, accessArguments.executeCreate(receiver, arguments)); } else { return doNext(frame, receiver, arguments); } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java --- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java Wed Nov 11 15:59:56 2015 -0800 @@ -130,9 +130,7 @@ } private void checkThread() { - if (initThread != Thread.currentThread()) { - throw new IllegalStateException("ForeignAccess created on " + initThread.getName() + " but used on " + Thread.currentThread().getName()); - } + assert initThread == Thread.currentThread(); } CallTarget access(Message message) { diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java --- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java Wed Nov 11 15:59:56 2015 -0800 @@ -24,19 +24,41 @@ */ package com.oracle.truffle.api.interop; -final class ForeignAccessArguments { +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.nodes.Node; + +final class ForeignAccessArguments extends Node { + static final Object[] EMPTY_ARGUMENTS_ARRAY = new Object[0]; static final int RECEIVER_INDEX = 0; static final int RUNTIME_ARGUMENT_COUNT = 1; - static Object[] create(Object receiver, Object... arguments) { - if (arguments.length == 0) { - return new Object[]{receiver}; + @CompilationFinal private int previousLength = -2; + + public Object[] executeCreate(Object receiver, Object... arguments) { + int length = profileLength(arguments.length); + Object[] objectArguments = new Object[RUNTIME_ARGUMENT_COUNT + length]; + objectArguments[RECEIVER_INDEX] = receiver; + arraycopy(arguments, 0, objectArguments, RUNTIME_ARGUMENT_COUNT, length); + return objectArguments; + } + + private int profileLength(int length) { + int returnLength = length; + if (previousLength != -1) { + if (previousLength == length) { + returnLength = previousLength; + } else { + CompilerDirectives.transferToInterpreterAndInvalidate(); + if (previousLength == -2) { + previousLength = length; + } else { + previousLength = -1; + } + } } - Object[] objectArguments = new Object[RUNTIME_ARGUMENT_COUNT + arguments.length]; - objectArguments[RECEIVER_INDEX] = receiver; - arraycopy(arguments, 0, objectArguments, RUNTIME_ARGUMENT_COUNT, arguments.length); - return objectArguments; + return returnLength; } private static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GenericObjectAccessNode.java --- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GenericObjectAccessNode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GenericObjectAccessNode.java Wed Nov 11 15:59:56 2015 -0800 @@ -34,6 +34,8 @@ private final Message access; @Child private IndirectCallNode indirectCallNode; + @Child private ForeignAccessArguments accessArguments = new ForeignAccessArguments(); + public GenericObjectAccessNode(Message access) { this.access = access; indirectCallNode = Truffle.getRuntime().createIndirectCallNode(); @@ -50,7 +52,7 @@ if (ct == null) { throw messageNotRecognizedException(fa); } - return indirectCallNode.call(frame, ct, ForeignAccessArguments.create(truffleObject, arguments)); + return indirectCallNode.call(frame, ct, accessArguments.executeCreate(truffleObject, arguments)); } @CompilerDirectives.TruffleBoundary diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java Wed Nov 11 15:59:56 2015 -0800 @@ -35,10 +35,6 @@ * An object may change its shape but only to shapes of the same layout. */ public abstract class Layout { - @Deprecated public static final EnumSet NONE = EnumSet.noneOf(ImplicitCast.class); - @Deprecated public static final EnumSet INT_TO_DOUBLE = EnumSet.of(ImplicitCast.IntToDouble); - @Deprecated public static final EnumSet INT_TO_LONG = EnumSet.of(ImplicitCast.IntToLong); - public static final String OPTION_PREFIX = "truffle.object."; private static final LayoutFactory LAYOUT_FACTORY = loadLayoutFactory(); @@ -65,15 +61,6 @@ return newLayout().build(); } - /** - * Equivalent to - * {@code Layout.newLayout().setAllowedImplicitCasts(allowedImplicitCasts).build()}. - */ - @Deprecated - public static Layout createLayout(EnumSet allowedImplicitCasts) { - return newLayout().setAllowedImplicitCasts(allowedImplicitCasts).build(); - } - public abstract DynamicObject newInstance(Shape shape); public abstract Class getType(); @@ -134,6 +121,7 @@ */ public static final class Builder { private EnumSet allowedImplicitCasts; + private boolean polymorphicUnboxing; /** * Create a new layout builder. @@ -169,13 +157,20 @@ return this; } - @Deprecated - public EnumSet getAllowedImplicitCasts() { - return allowedImplicitCasts; + /** + * If {@code true}, try to keep properties with polymorphic primitive types unboxed. + */ + public Builder setPolymorphicUnboxing(boolean polymorphicUnboxing) { + this.polymorphicUnboxing = polymorphicUnboxing; + return this; } } protected static EnumSet getAllowedImplicitCasts(Builder builder) { return builder.allowedImplicitCasts; } + + protected static boolean getPolymorphicUnboxing(Builder builder) { + return builder.polymorphicUnboxing; + } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java --- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java Wed Nov 11 15:59:56 2015 -0800 @@ -65,6 +65,7 @@ return null; } + @Deprecated public ForeignAccess getForeignAccessFactory() { return ForeignAccess.create(new com.oracle.truffle.api.interop.ForeignAccess.Factory() { @@ -77,4 +78,13 @@ } }); } + + /** + * Create a {@link ForeignAccess} to access a specific {@link DynamicObject}. + * + * @param object the object to be accessed + */ + public ForeignAccess getForeignAccessFactory(DynamicObject object) { + return getForeignAccessFactory(); + } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -58,7 +58,7 @@ public void before() { // TODO (mlvdv) eventually abstract this try { - vm = PolyglotEngine.buildNew().build(); + vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); instrumenter = (Instrumenter) field.get(vm); @@ -99,7 +99,7 @@ final Source source42 = InstrumentationTestingLanguage.createConstantSource42("testEvalInstrumentListener"); final int[] evalResult = {0}; final int[] evalCount = {0}; - final Instrument instrument = instrumenter.attach(addNodeProbe[0], InstrumentationTestingLanguage.class, source42, new EvalInstrumentListener() { + final Instrument instrument = instrumenter.attach(addNodeProbe[0], source42, new EvalInstrumentListener() { public void onExecution(Node node, VirtualFrame vFrame, Object result) { evalCount[0] = evalCount[0] + 1; @@ -112,7 +112,7 @@ fail("Eval test evaluates without exception"); } - }, "test EvalInstrument"); + }, "test EvalInstrument", null); assertEquals(vm.eval(source13).get(), 13); assertEquals(evalCount[0], 1); @@ -124,7 +124,7 @@ assertEquals(evalResult[0], 42); // Add new eval instrument with no listener, no effect on third execution - instrumenter.attach(addNodeProbe[0], InstrumentationTestingLanguage.class, source42, null, ""); + instrumenter.attach(addNodeProbe[0], source42, null, "", null); assertEquals(vm.eval(source13).get(), 13); assertEquals(evalCount[0], 3); assertEquals(evalResult[0], 42); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -64,7 +64,7 @@ @Test public void testProbing() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); @@ -106,7 +106,7 @@ @Test public void testTagging() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); @@ -243,10 +243,9 @@ leaveCount++; } - public void onReturnExceptional(Probe p, Exception exception) { + public void onReturnExceptional(Probe p, Throwable exception) { leaveCount++; } - }, "Instrumentation Test Counter"); } @@ -296,10 +295,9 @@ leaveCount++; } - public void onReturnExceptional(Probe p, Node node, VirtualFrame vFrame, Exception exception) { + public void onReturnExceptional(Probe p, Node node, VirtualFrame vFrame, Throwable exception) { leaveCount++; } - }, "Instrumentation Test Counter"); } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/interop/ForeignAccessSingleThreadedTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/interop/ForeignAccessSingleThreadedTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/interop/ForeignAccessSingleThreadedTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -49,7 +49,7 @@ t.join(); } - @Test(expected = IllegalStateException.class) + @Test(expected = AssertionError.class) public void accessNodeFromWrongThread() { Node n = Message.IS_EXECUTABLE.createNode(); Object ret = ForeignAccess.execute(n, null, this); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/InstrumentationTestMode.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/InstrumentationTestMode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/InstrumentationTestMode.java Wed Nov 11 15:59:56 2015 -0800 @@ -34,7 +34,7 @@ public static void set(boolean enable) { try { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field instrumenterField = vm.getClass().getDeclaredField("instrumenter"); instrumenterField.setAccessible(true); final Object instrumenter = instrumenterField.get(vm); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/AccessorTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -50,7 +50,7 @@ @Test public void canGetAccessToOwnLanguageInstance() throws Exception { - PolyglotEngine vm = PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()).build(); + PolyglotEngine vm = PolyglotEngine.newBuilder().executor(Executors.newSingleThreadExecutor()).build(); PolyglotEngine.Language language = vm.getLanguages().get(L1); assertNotNull("L1 language is defined", language); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineAsynchTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineAsynchTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineAsynchTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -38,6 +38,6 @@ @Override protected PolyglotEngine.Builder createBuilder() { - return PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()); + return PolyglotEngine.newBuilder().executor(Executors.newSingleThreadExecutor()); } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineSingleThreadedTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineSingleThreadedTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineSingleThreadedTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -24,10 +24,9 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; +import java.io.File; import java.io.IOException; import java.io.StringReader; -import java.net.URI; -import java.net.URISyntaxException; import org.junit.Before; import org.junit.Test; @@ -36,7 +35,7 @@ @Before public void initInDifferentThread() throws InterruptedException { - final PolyglotEngine.Builder b = PolyglotEngine.buildNew(); + final PolyglotEngine.Builder b = PolyglotEngine.newBuilder(); Thread t = new Thread("Initializer") { @Override public void run() { @@ -47,23 +46,20 @@ t.join(); } - @SuppressWarnings("deprecation") @Test(expected = IllegalStateException.class) - public void evalURI() throws IOException, URISyntaxException { - tvm.eval(new URI("http://unknown.js")); + public void evalURI() throws IOException { + tvm.eval(Source.fromURL(new File(".").toURI().toURL(), "wrong.test")); } - @SuppressWarnings("deprecation") @Test(expected = IllegalStateException.class) public void evalString() throws IOException { - tvm.eval("text/javascript", "1 + 1"); + tvm.eval(Source.fromText("1 + 1", "wrong.test").withMimeType("text/javascript")); } - @SuppressWarnings("deprecation") @Test(expected = IllegalStateException.class) public void evalReader() throws IOException { try (StringReader sr = new StringReader("1 + 1")) { - tvm.eval("text/javascript", sr); + tvm.eval(Source.fromReader(sr, "wrong.test").withMimeType("text/javascript")); } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/EngineTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -31,7 +31,7 @@ public class EngineTest { protected PolyglotEngine.Builder createBuilder() { - return PolyglotEngine.buildNew(); + return PolyglotEngine.newBuilder(); } @Test diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ExceptionDuringParsingTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -47,7 +47,7 @@ @Test public void canGetAccessToOwnLanguageInstance() throws Exception { - PolyglotEngine vm = PolyglotEngine.buildNew().build(); + PolyglotEngine vm = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language language = vm.getLanguages().get(L1); assertNotNull("L1 language is defined", language); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolAsynchTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolAsynchTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolAsynchTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -35,6 +35,6 @@ @Override protected PolyglotEngine.Builder createEngineBuilder() { - return PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()); + return PolyglotEngine.newBuilder().executor(Executors.newSingleThreadExecutor()); } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -74,7 +74,7 @@ } protected PolyglotEngine.Builder createEngineBuilder() { - return PolyglotEngine.buildNew(); + return PolyglotEngine.newBuilder(); } @Test diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -60,7 +60,7 @@ @Before public void initializeVM() { mainThread = Thread.currentThread(); - vm = PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()).build(); + vm = PolyglotEngine.newBuilder().executor(Executors.newSingleThreadExecutor()).build(); assertTrue("Found " + L1 + " language", vm.getLanguages().containsKey(L1)); assertTrue("Found " + L2 + " language", vm.getLanguages().containsKey(L2)); assertTrue("Found " + L3 + " language", vm.getLanguages().containsKey(L3)); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -71,7 +71,7 @@ @Test public void accessProbeForAbstractLanguage() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { final Debugger[] arr = {null}; - PolyglotEngine vm = PolyglotEngine.buildNew().onEvent(new EventConsumer(ExecutionEvent.class) { + PolyglotEngine vm = PolyglotEngine.newBuilder().onEvent(new EventConsumer(ExecutionEvent.class) { @Override protected void on(ExecutionEvent event) { arr[0] = event.getDebugger(); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ToStringTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ToStringTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ToStringTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -30,7 +30,7 @@ public class ToStringTest { @Test public void valueToStringValueWith1() throws Exception { - PolyglotEngine engine = PolyglotEngine.buildNew().build(); + PolyglotEngine engine = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1"); PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2"); language2.eval(Source.fromText("explicit.value=42", "define 42")); @@ -43,7 +43,7 @@ @Test public void valueToStringValueWith2() throws Exception { - PolyglotEngine engine = PolyglotEngine.buildNew().build(); + PolyglotEngine engine = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1"); PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2"); language1.eval(Source.fromText("explicit.value=42", "define 42")); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ValueTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ValueTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ValueTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -41,7 +41,7 @@ @Test public void valueToStringValue() throws Exception { - PolyglotEngine engine = PolyglotEngine.buildNew().build(); + PolyglotEngine engine = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1"); PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2"); language2.eval(Source.fromText("explicit.value=42", "define 42")); @@ -56,7 +56,7 @@ @Test public void valueToStringException() throws Exception { - PolyglotEngine engine = PolyglotEngine.buildNew().build(); + PolyglotEngine engine = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1"); PolyglotEngine.Value value = null; try { @@ -72,7 +72,7 @@ @Test public void valueToStringValueAsync() throws Exception { - PolyglotEngine engine = PolyglotEngine.buildNew().executor(this).build(); + PolyglotEngine engine = PolyglotEngine.newBuilder().executor(this).build(); PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1"); PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2"); language2.eval(Source.fromText("explicit.value=42", "define 42")); @@ -96,7 +96,7 @@ @Test public void valueToStringExceptionAsync() throws Exception { - PolyglotEngine engine = PolyglotEngine.buildNew().executor(this).build(); + PolyglotEngine engine = PolyglotEngine.newBuilder().executor(this).build(); PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1"); PolyglotEngine.Value value = language1.eval(Source.fromText("parse=does not work", "error.value")); assertNotNull("Value returned", value); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.vm/src/META-INF/upgrade/PolyglotEngineNewBuilder.hint --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api.vm/src/META-INF/upgrade/PolyglotEngineNewBuilder.hint Wed Nov 11 15:59:56 2015 -0800 @@ -0,0 +1,6 @@ +'PolyglotEngine.buildNew() is misleading': +com.oracle.truffle.api.vm.PolyglotEngine.buildNew() +=> +'Use newBuilder()': +com.oracle.truffle.api.vm.PolyglotEngine.newBuilder() +;; diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/ComputeInExecutor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/ComputeInExecutor.java Wed Nov 11 15:59:56 2015 -0800 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.vm; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.util.concurrent.Executor; + +abstract class ComputeInExecutor implements Runnable { + private final Executor executor; + private R result; + private Throwable exception; + private boolean started; + private boolean done; + + protected ComputeInExecutor(Executor executor) { + this.executor = executor; + } + + protected abstract R compute() throws IOException; + + public final R get() throws IOException { + perform(); + if (executor != null) { + waitForDone(); + } + exceptionCheck(); + return result; + } + + private void waitForDone() throws InterruptedIOException { + synchronized (this) { + while (!done) { + try { + wait(); + } catch (InterruptedException ex) { + throw new InterruptedIOException(ex.getMessage()); + } + } + } + } + + private void exceptionCheck() throws IOException, RuntimeException { + if (exception instanceof IOException) { + throw (IOException) exception; + } + if (exception instanceof RuntimeException) { + throw (RuntimeException) exception; + } + if (exception != null) { + throw new RuntimeException(exception); + } + } + + public final void perform() throws IOException { + if (started) { + return; + } + started = true; + if (executor == null) { + run(); + } else { + executor.execute(this); + } + exceptionCheck(); + } + + @Override + public final void run() { + try { + result = compute(); + } catch (Exception ex) { + exception = ex; + } finally { + if (executor != null) { + synchronized (this) { + done = true; + notifyAll(); + } + } else { + done = true; + } + } + } + + @Override + public final String toString() { + return "value=" + result + ",exception=" + exception + ",computed=" + done; + } +} diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/IncompleteSourceException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/IncompleteSourceException.java Wed Nov 11 15:59:56 2015 -0800 @@ -0,0 +1,19 @@ +package com.oracle.truffle.api.vm; + +import java.io.IOException; + +/** + * Indicates that the provided source was incomplete and requires further text to be executed. + */ +@SuppressWarnings("serial") +public class IncompleteSourceException extends IOException { + + public IncompleteSourceException() { + super(); + } + + public IncompleteSourceException(Throwable cause) { + super(cause); + } + +} diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/LanguageCache.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/LanguageCache.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/LanguageCache.java Wed Nov 11 15:59:56 2015 -0800 @@ -25,6 +25,7 @@ package com.oracle.truffle.api.vm; import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.TruffleOptions; import static com.oracle.truffle.api.vm.PolyglotEngine.LOG; import java.io.IOException; import java.io.InputStream; @@ -39,8 +40,8 @@ import java.util.logging.Level; /** - * Ahead-of-time initialization. If the JVM is started with -Dcom.oracle.truffle.aot=true, it - * populates cache with languages found in application classloader. + * Ahead-of-time initialization. If the JVM is started with {@link TruffleOptions#AOT}, it populates + * cache with languages found in application classloader. */ final class LanguageCache { static final boolean PRELOAD; @@ -53,7 +54,7 @@ static { Map map = null; - if (Boolean.getBoolean("com.oracle.truffle.aot")) { // NOI18N + if (TruffleOptions.AOT) { map = languages(); for (LanguageCache info : map.values()) { info.getImpl(true); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java Wed Nov 11 15:59:56 2015 -0800 @@ -25,17 +25,9 @@ package com.oracle.truffle.api.vm; import java.io.Closeable; -import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.InterruptedIOException; import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.URI; -import java.net.URL; -import java.net.URLConnection; -import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -45,25 +37,25 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.logging.Level; import java.util.logging.Logger; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLanguage.Registration; +import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.debug.ExecutionEvent; import com.oracle.truffle.api.debug.SuspendedEvent; +import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.impl.Accessor; import com.oracle.truffle.api.instrument.Instrumenter; -import com.oracle.truffle.api.instrument.KillException; import com.oracle.truffle.api.instrument.Probe; -import com.oracle.truffle.api.instrument.QuitException; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.java.JavaInterop; @@ -94,11 +86,12 @@ * Use {@link #buildNew()} multiple times to create different, isolated portal environment * completely separated from each other. *

- * Once instantiated use {@link #eval(java.net.URI)} with a reference to a file or URL or directly - * pass code snippet into the virtual machine via {@link #eval(java.lang.String, java.lang.String)}. - * Support for individual languages is initialized on demand - e.g. once a file of certain MIME type - * is about to be processed, its appropriate engine (if found), is initialized. Once an engine gets - * initialized, it remains so, until the virtual machine isn't garbage collected. + * Once instantiated use {@link #eval(com.oracle.truffle.api.source.Source)} with a reference to a + * file or URL or directly pass code snippet into the virtual machine via + * {@link #eval(com.oracle.truffle.api.source.Source)}. Support for individual languages is + * initialized on demand - e.g. once a file of certain MIME type is about to be processed, its + * appropriate engine (if found), is initialized. Once an engine gets initialized, it remains so, + * until the virtual machine isn't garbage collected. *

* The engine is single-threaded and tries to enforce that. It records the thread it has been * {@link Builder#build() created} by and checks that all subsequent calls are coming from the same @@ -107,8 +100,7 @@ */ @SuppressWarnings("rawtypes") public class PolyglotEngine { - static final boolean JAVA_INTEROP_ENABLED = !Boolean.getBoolean("com.oracle.truffle.aot"); - + static final boolean JAVA_INTEROP_ENABLED = !TruffleOptions.AOT; static final Logger LOG = Logger.getLogger(PolyglotEngine.class.getName()); private static final SPIAccessor SPI = new SPIAccessor(); private final Thread initThread; @@ -178,11 +170,11 @@ * * It searches for {@link Registration languages registered} in the system class loader and * makes them available for later evaluation via - * {@link #eval(java.lang.String, java.lang.String)} methods. + * {@link #eval(com.oracle.truffle.api.source.Source)} method. * - * @return new, isolated virtual machine with pre-registered languages + * @return new builder to create isolated polyglot engine with pre-registered languages */ - public static PolyglotEngine.Builder buildNew() { + public static PolyglotEngine.Builder newBuilder() { // making Builder non-static inner class is a // nasty trick to avoid the Builder class to appear // in Javadoc next to PolyglotEngine class @@ -191,6 +183,15 @@ } /** + * @return new builder + * @deprecated use {@link #newBuilder()} + */ + @Deprecated + public static PolyglotEngine.Builder buildNew() { + return newBuilder(); + } + + /** * Builder for a new {@link PolyglotEngine}. Call various configuration methods in a chain and * at the end create new {@link PolyglotEngine virtual machine}: * @@ -226,15 +227,6 @@ } /** - * @deprecated does nothing - */ - @Deprecated - @SuppressWarnings("unused") - public Builder stdOut(Writer w) { - return this; - } - - /** * Changes the error output for languages running in to be created * {@link PolyglotEngine virtual machine}. The default is to use {@link System#err}. * @@ -247,15 +239,6 @@ } /** - * @deprecated does nothing - */ - @Deprecated - @SuppressWarnings("unused") - public Builder stdErr(Writer w) { - return this; - } - - /** * Changes the default input for languages running in to be created * {@link PolyglotEngine virtual machine}. The default is to use {@link System#in}. * @@ -268,15 +251,6 @@ } /** - * @deprecated does nothing - */ - @Deprecated - @SuppressWarnings("unused") - public Builder stdIn(Reader r) { - return this; - } - - /** * Registers another instance of {@link EventConsumer} into the to be created * {@link PolyglotEngine}. * @@ -299,16 +273,24 @@ * * @param name name of the symbol to register * @param obj value of the object - expected to be primitive wrapper, {@link String} or - * TruffleObject for mutual inter-operability + * TruffleObject for mutual inter-operability. If the object isn't + * of the previous types, the system tries to wrap it using + * {@link JavaInterop#asTruffleObject(java.lang.Object)}, if available * @return instance of this builder * @see PolyglotEngine#findGlobalSymbol(java.lang.String) + * @throws IllegalArgumentException if the object isn't of primitive type and cannot be + * converted to {@link TruffleObject} */ public Builder globalSymbol(String name, Object obj) { final Object truffleReady; - if (obj instanceof Number || obj instanceof String || obj instanceof Character || obj instanceof Boolean) { + if (obj instanceof TruffleObject || obj instanceof Number || obj instanceof String || obj instanceof Character || obj instanceof Boolean) { truffleReady = obj; } else { - truffleReady = JavaInterop.asTruffleObject(obj); + if (JAVA_INTEROP_ENABLED) { + truffleReady = JavaInterop.asTruffleObject(obj); + } else { + throw new IllegalArgumentException(); + } } globals.put(name, truffleReady); return this; @@ -351,13 +333,7 @@ if (in == null) { in = System.in; } - Executor nonNullExecutor = executor != null ? executor : new Executor() { - @Override - public void execute(Runnable command) { - command.run(); - } - }; - return new PolyglotEngine(nonNullExecutor, globals, out, err, in, handlers.toArray(new EventConsumer[0])); + return new PolyglotEngine(executor, globals, out, err, in, handlers.toArray(new EventConsumer[0])); } } @@ -372,79 +348,6 @@ } /** - * Evaluates file located on a given URL. Is equivalent to loading the content of a file and - * executing it via {@link #eval(java.lang.String, java.lang.String)} with a MIME type guess - * based on the file's extension and/or content. - * - * @param location the location of a file to execute - * @return result of a processing the file, possibly null - * @throws IOException exception to signal I/O problems or problems with processing the file's - * content - * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} - */ - @Deprecated - public Object eval(URI location) throws IOException { - checkThread(); - Source s; - String mimeType; - if (location.getScheme().equals("file")) { - File file = new File(location); - s = Source.fromFileName(file.getPath(), true); - mimeType = Files.probeContentType(file.toPath()); - } else { - URL url = location.toURL(); - s = Source.fromURL(url, location.toString()); - URLConnection conn = url.openConnection(); - mimeType = conn.getContentType(); - } - Language l = langs.get(mimeType); - if (l == null) { - throw new IOException("No language for " + location + " with MIME type " + mimeType + " found. Supported types: " + langs.keySet()); - } - return eval(l, s).get(); - } - - /** - * Evaluates code snippet. Chooses a language registered for a given MIME type (throws - * {@link IOException} if there is none). And passes the specified code to it for execution. - * - * @param mimeType MIME type of the code snippet - chooses the right language - * @param reader the source of code snippet to execute - * @return result of an execution, possibly null - * @throws IOException thrown to signal errors while processing the code - * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} - */ - @Deprecated - public Object eval(String mimeType, Reader reader) throws IOException { - checkThread(); - Language l = langs.get(mimeType); - if (l == null) { - throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet()); - } - return eval(l, Source.fromReader(reader, mimeType)).get(); - } - - /** - * Evaluates code snippet. Chooses a language registered for a given MIME type (throws - * {@link IOException} if there is none). And passes the specified code to it for execution. - * - * @param mimeType MIME type of the code snippet - chooses the right language - * @param code the code snippet to execute - * @return result of an execution, possibly null - * @throws IOException thrown to signal errors while processing the code - * @deprecated use {@link #eval(com.oracle.truffle.api.source.Source)} - */ - @Deprecated - public Object eval(String mimeType, String code) throws IOException { - checkThread(); - Language l = langs.get(mimeType); - if (l == null) { - throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet()); - } - return eval(l, Source.fromText(code, mimeType)).get(); - } - - /** * Evaluates provided source. Chooses language registered for a particular * {@link Source#getMimeType() MIME type} (throws {@link IOException} if there is none). The * language is then allowed to parse and execute the source. @@ -475,9 +378,9 @@ public void dispose() { checkThread(); disposed = true; - executor.execute(new Runnable() { + ComputeInExecutor compute = new ComputeInExecutor(executor) { @Override - public void run() { + protected Void compute() throws IOException { for (Language language : getLanguages().values()) { TruffleLanguage impl = language.getImpl(false); if (impl != null) { @@ -488,26 +391,26 @@ } } } + return null; } - }); + }; + try { + compute.perform(); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } } private Value eval(final Language l, final Source s) throws IOException { - final Object[] result = {null, null}; - final CountDownLatch ready = new CountDownLatch(1); final TruffleLanguage[] lang = {null}; - executor.execute(new Runnable() { + ComputeInExecutor compute = new ComputeInExecutor(executor) { @Override - public void run() { - evalImpl(lang, s, result, l, ready); + protected Object compute() throws IOException { + return evalImpl(lang, s, l); } - }); - exceptionCheck(result); - return createValue(lang, result, ready); - } - - Value createValue(TruffleLanguage[] lang, Object[] result, CountDownLatch ready) { - return new Value(lang, result, ready); + }; + compute.perform(); + return new Value(lang, compute); } Language createLanguage(Map.Entry en) { @@ -515,58 +418,53 @@ } @SuppressWarnings("try") - private void evalImpl(TruffleLanguage[] fillLang, Source s, Object[] result, Language l, CountDownLatch ready) { + private Object evalImpl(TruffleLanguage[] fillLang, Source s, Language l) throws IOException { try (Closeable d = SPI.executionStart(this, -1, debugger, s)) { TruffleLanguage langImpl = l.getImpl(true); fillLang[0] = langImpl; - result[0] = SPI.eval(langImpl, s); - } catch (IOException ex) { - result[1] = ex; - } finally { - ready.countDown(); + return SPI.eval(langImpl, s); } } @SuppressWarnings("try") - final Object invokeForeign(final Node foreignNode, final VirtualFrame frame, final TruffleObject receiver) throws IOException { - final Object[] res = {null, null}; - final CountDownLatch computed = new CountDownLatch(1); - final Thread caller = Thread.currentThread(); - executor.execute(new Runnable() { + final Object invokeForeign(final Node foreignNode, VirtualFrame frame, final TruffleObject receiver) throws IOException { + Object res; + if (executor == null) { + try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) { + final Object[] args = ForeignAccess.getArguments(frame).toArray(); + res = ForeignAccess.execute(foreignNode, frame, receiver, args); + } + } else { + res = invokeForeignOnExecutor(foreignNode, frame, receiver); + } + if (res instanceof TruffleObject) { + return new EngineTruffleObject(this, (TruffleObject) res); + } else { + return res; + } + } + + @TruffleBoundary + private Object invokeForeignOnExecutor(final Node foreignNode, VirtualFrame frame, final TruffleObject receiver) throws IOException { + final MaterializedFrame materialized = frame.materialize(); + ComputeInExecutor compute = new ComputeInExecutor(executor) { + @SuppressWarnings("try") @Override - public void run() { + protected Object compute() throws IOException { try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) { - final Object[] args = ForeignAccess.getArguments(frame).toArray(); - if (caller != Thread.currentThread()) { - RootNode node = SymbolInvokerImpl.createTemporaryRoot(TruffleLanguage.class, foreignNode, receiver, args.length); - final CallTarget target = Truffle.getRuntime().createCallTarget(node); - res[0] = target.call(args); - } else { - res[0] = ForeignAccess.execute(foreignNode, frame, receiver, args); - } - } catch (Exception ex) { - res[1] = ex; - } finally { - computed.countDown(); + final Object[] args = ForeignAccess.getArguments(materialized).toArray(); + RootNode node = SymbolInvokerImpl.createTemporaryRoot(TruffleLanguage.class, foreignNode, receiver, args.length); + final CallTarget target = Truffle.getRuntime().createCallTarget(node); + return target.call(args); } } - }); - try { - computed.await(); - } catch (InterruptedException ex) { - throw new InterruptedIOException(ex.getMessage()); - } - exceptionCheck(res); - if (res[0] instanceof TruffleObject) { - return new EngineTruffleObject(this, (TruffleObject) res[0]); - } else { - return res[0]; - } + }; + return compute.get(); } /** * Looks global symbol provided by one of initialized languages up. First of all execute your - * program via one of your {@link #eval(java.lang.String, java.lang.String)} and then look + * program via one of your {@link #eval(com.oracle.truffle.api.source.Source)} and then look * expected symbol up using this method. *

* The names of the symbols are language dependent, but for example the Java language bindings @@ -584,54 +482,48 @@ public Value findGlobalSymbol(final String globalName) { checkThread(); final TruffleLanguage[] lang = {null}; - final Object[] obj = {globals.get(globalName), null}; - final CountDownLatch ready = new CountDownLatch(1); - if (obj[0] == null) { - executor.execute(new Runnable() { - @Override - public void run() { - findGlobalSymbolImpl(obj, globalName, lang, ready); + ComputeInExecutor compute = new ComputeInExecutor(executor) { + @Override + protected Object compute() throws IOException { + Object obj = globals.get(globalName); + if (obj == null) { + for (Language dl : langs.values()) { + TruffleLanguage.Env env = dl.getEnv(false); + if (env == null) { + continue; + } + obj = SPI.findExportedSymbol(env, globalName, true); + if (obj != null) { + lang[0] = dl.getImpl(true); + break; + } + } } - }); - try { - ready.await(); - } catch (InterruptedException ex) { - LOG.log(Level.SEVERE, null, ex); + if (obj == null) { + for (Language dl : langs.values()) { + TruffleLanguage.Env env = dl.getEnv(false); + if (env == null) { + continue; + } + obj = SPI.findExportedSymbol(env, globalName, true); + if (obj != null) { + lang[0] = dl.getImpl(true); + break; + } + } + } + return obj; } - } else { - ready.countDown(); + }; + try { + compute.perform(); + if (compute.get() == null) { + return null; + } + } catch (IOException ex) { + // OK, go on } - return obj[0] == null ? null : createValue(lang, obj, ready); - } - - private void findGlobalSymbolImpl(Object[] obj, String globalName, TruffleLanguage[] lang, CountDownLatch ready) { - if (obj[0] == null) { - for (Language dl : langs.values()) { - TruffleLanguage.Env env = dl.getEnv(false); - if (env == null) { - continue; - } - obj[0] = SPI.findExportedSymbol(env, globalName, true); - if (obj[0] != null) { - lang[0] = dl.getImpl(true); - break; - } - } - } - if (obj[0] == null) { - for (Language dl : langs.values()) { - TruffleLanguage.Env env = dl.getEnv(false); - if (env == null) { - continue; - } - obj[0] = SPI.findExportedSymbol(env, globalName, true); - if (obj[0] != null) { - lang[0] = dl.getImpl(true); - break; - } - } - } - ready.countDown(); + return new Value(lang, compute); } private void checkThread() { @@ -672,15 +564,6 @@ } } - static void exceptionCheck(Object[] result) throws RuntimeException, IOException { - if (result[1] instanceof IOException) { - throw (IOException) result[1]; - } - if (result[1] instanceof RuntimeException) { - throw (RuntimeException) result[1]; - } - } - /** * A future value wrapper. A user level wrapper around values returned by evaluation of various * {@link PolyglotEngine} functions like @@ -694,14 +577,22 @@ */ public class Value { private final TruffleLanguage[] language; - private final Object[] result; - private final CountDownLatch ready; + private final ComputeInExecutor compute; private CallTarget target; - Value(TruffleLanguage[] language, Object[] result, CountDownLatch ready) { + Value(TruffleLanguage[] language, ComputeInExecutor compute) { + this.language = language; + this.compute = compute; + } + + Value(TruffleLanguage[] language, final Object value) { this.language = language; - this.result = result; - this.ready = ready; + this.compute = new ComputeInExecutor(null) { + @Override + protected Object compute() throws IOException { + return value; + } + }; } /** @@ -714,12 +605,11 @@ * @throws IOException in case it is not possible to obtain the value of the object */ public Object get() throws IOException { - waitForSymbol(); - exceptionCheck(result); - if (result[0] instanceof TruffleObject) { - return new EngineTruffleObject(PolyglotEngine.this, (TruffleObject) result[0]); + Object result = waitForSymbol(); + if (result instanceof TruffleObject) { + return new EngineTruffleObject(PolyglotEngine.this, (TruffleObject) result); } else { - return result[0]; + return result; } } @@ -778,69 +668,48 @@ */ public Value invoke(final Object thiz, final Object... args) throws IOException { get(); - final CountDownLatch done = new CountDownLatch(1); - final Object[] res = {null, null}; - executor.execute(new Runnable() { + ComputeInExecutor invokeCompute = new ComputeInExecutor(executor) { + @SuppressWarnings("try") @Override - public void run() { - invokeImpl(thiz, args, res, done); - } - }); - exceptionCheck(res); - return createValue(language, res, done); - } - - @SuppressWarnings("try") - private void invokeImpl(Object thiz, Object[] args, Object[] res, CountDownLatch done) { - try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) { - List arr = new ArrayList<>(); - if (thiz == null) { - if (language[0] != null) { - Object global = SPI.languageGlobal(SPI.findLanguage(PolyglotEngine.this, language[0].getClass())); - if (global != null) { - arr.add(global); + protected Object compute() throws IOException { + try (final Closeable c = SPI.executionStart(PolyglotEngine.this, -1, debugger, null)) { + List arr = new ArrayList<>(); + if (thiz == null) { + if (language[0] != null) { + Object global = SPI.languageGlobal(SPI.findLanguage(PolyglotEngine.this, language[0].getClass())); + if (global != null) { + arr.add(global); + } + } + } else { + arr.add(thiz); + } + arr.addAll(Arrays.asList(args)); + for (;;) { + try { + if (target == null) { + target = SymbolInvokerImpl.createCallTarget(language[0], compute.get(), arr.toArray()); + } + return target.call(arr.toArray()); + } catch (ArgumentsMishmashException ex) { + target = null; + } } } - } else { - arr.add(thiz); } - arr.addAll(Arrays.asList(args)); - for (;;) { - try { - if (target == null) { - target = SymbolInvokerImpl.createCallTarget(language[0], result[0], arr.toArray()); - } - res[0] = target.call(arr.toArray()); - break; - } catch (ArgumentsMishmashException ex) { - target = null; - } - } - } catch (KillException | QuitException ex) { - throw ex; - } catch (IOException ex) { - res[1] = ex; - } catch (RuntimeException ex) { - res[1] = ex; - } finally { - done.countDown(); - } + }; + invokeCompute.perform(); + return new Value(language, invokeCompute); } - private void waitForSymbol() throws InterruptedIOException { + private Object waitForSymbol() throws IOException { checkThread(); - try { - if (ready != null) { - ready.await(); - } - } catch (InterruptedException ex) { - throw (InterruptedIOException) new InterruptedIOException(ex.getMessage()).initCause(ex); - } + return compute.get(); } @Override public String toString() { - return "PolyglotEngine.Value[value=" + result[0] + ",exception=" + result[1] + ",computed=" + (ready.getCount() == 0) + "]"; + return "PolyglotEngine.Value[" + compute + "]"; } } @@ -852,7 +721,7 @@ * {@link Language} objects to represent them. One can obtain a {@link #getName() name} or list * of supported {@link #getMimeTypes() MIME types} for each language. The actual language * implementation is not initialized until - * {@link PolyglotEngine#eval(java.lang.String, java.lang.String) a code is evaluated} in it. + * {@link PolyglotEngine#eval(com.oracle.truffle.api.source.Source) a code is evaluated} in it. */ public class Language { private final LanguageCache info; @@ -914,16 +783,8 @@ public Value getGlobalObject() { checkThread(); - Object[] res = {SPI.languageGlobal(getEnv(true)), null}; - return res[0] == null ? null : new Value(new TruffleLanguage[]{info.getImpl(true)}, res, null); - } - - /** - * @deprecated concatenate {@link #getName()} and {@link #getVersion()} the way you want. - */ - @Deprecated - public String getShortName() { - return getName() + "(" + getVersion() + ")"; + Object res = SPI.languageGlobal(getEnv(true)); + return res == null ? null : new Value(new TruffleLanguage[]{info.getImpl(true)}, res); } TruffleLanguage getImpl(boolean create) { @@ -941,7 +802,7 @@ @Override public String toString() { - return "[" + getShortName() + " for " + getMimeTypes() + "]"; + return "[" + getName() + "@ " + getVersion() + " for " + getMimeTypes() + "]"; } } // end of Language @@ -957,7 +818,15 @@ return impl; } } - throw new IllegalStateException("Cannot find language " + languageClazz + " among " + langs); + return null; + } + + TruffleLanguage findLanguage(String mimeType) { + Language languageDescription = this.langs.get(mimeType); + if (languageDescription != null) { + return languageDescription.getImpl(true); + } + return null; } TruffleLanguage findLanguage(Probe probe) { @@ -1058,9 +927,19 @@ } @Override - protected TruffleLanguage findLanguageImpl(Object obj, Class languageClazz) { + protected TruffleLanguage findLanguageImpl(Object obj, Class languageClazz, String mimeType) { final PolyglotEngine vm = (PolyglotEngine) obj; - return vm.findLanguage(languageClazz); + TruffleLanguage language = null; + if (languageClazz != null) { + language = vm.findLanguage(languageClazz); + } + if (language == null && mimeType != null) { + language = vm.findLanguage(mimeType); + } + if (language == null) { + throw new IllegalStateException("Cannot find language " + languageClazz + " with mimeType" + mimeType + " among " + vm.langs); + } + return language; } @Override diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/TruffleVM.java Tue Nov 10 19:42:37 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.vm; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; - -import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.debug.ExecutionEvent; -import com.oracle.truffle.api.debug.SuspendedEvent; -import com.oracle.truffle.api.source.Source; - -/** - * @deprecated - */ -@Deprecated -@SuppressWarnings({"rawtypes", "deprecated"}) -public final class TruffleVM extends PolyglotEngine { - private TruffleVM() { - super(); - } - - /** - * Real constructor used from the builder. - */ - TruffleVM(Executor executor, Map globals, OutputStream out, OutputStream err, InputStream in, EventConsumer[] handlers) { - super(executor, globals, out, err, in, handlers); - } - - @Deprecated - public static TruffleVM.Builder newVM() { - // making Builder non-static inner class is a - // nasty trick to avoid the Builder class to appear - // in Javadoc next to TruffleVM class - TruffleVM vm = new TruffleVM(); - return vm.new Builder(); - } - - @SuppressWarnings("deprecation") - @Deprecated - public final class Builder extends PolyglotEngine.Builder { - Builder() { - } - - @Deprecated - @Override - public Builder setOut(OutputStream os) { - super.setOut(os); - return this; - } - - @Deprecated - @Override - public Builder executor(Executor executor) { - return (Builder) super.executor(executor); - } - - @Deprecated - @Override - public Builder setErr(OutputStream os) { - super.setErr(os); - return this; - } - - @Deprecated - @Override - public Builder globalSymbol(String name, Object obj) { - return (Builder) super.globalSymbol(name, obj); - } - - @Deprecated - @Override - public Builder setIn(InputStream is) { - super.setIn(is); - return this; - } - - @Deprecated - @Override - public Builder onEvent(EventConsumer handler) { - return (Builder) super.onEvent(handler); - } - - @Deprecated - @Override - public Builder stdIn(Reader r) { - return (Builder) super.stdIn(r); - } - - @Deprecated - @Override - public Builder stdErr(Writer w) { - return (Builder) super.stdErr(w); - } - - @Deprecated - @Override - public Builder stdOut(Writer w) { - return (Builder) super.stdOut(w); - } - - @Deprecated - @Override - public TruffleVM build() { - return (TruffleVM) super.build(); - } - } - - @Override - Value createValue(TruffleLanguage[] lang, Object[] result, CountDownLatch ready) { - return new Symbol(lang, result, ready); - } - - @Override - Language createLanguage(Map.Entry en) { - return new Language(en.getValue()); - } - - @Override - @SuppressWarnings("unchecked") - public Map getLanguages() { - return (Map) super.getLanguages(); - } - - @Override - public Symbol eval(Source source) throws IOException { - return (Symbol) super.eval(source); - } - - @Override - public Symbol findGlobalSymbol(final String globalName) { - return (Symbol) super.findGlobalSymbol(globalName); - } - - @Override - void dispatchSuspendedEvent(SuspendedEvent event) { - super.dispatchSuspendedEvent(event); - } - - @Override - void dispatchExecutionEvent(ExecutionEvent event) { - super.dispatchExecutionEvent(event); - } - - @Deprecated - public class Symbol extends Value { - Symbol(TruffleLanguage[] language, Object[] result, CountDownLatch ready) { - super(language, result, ready); - } - - @Override - public Symbol invoke(final Object thiz, final Object... args) throws IOException { - return (Symbol) super.invoke(thiz, args); - } - } - - @Deprecated - public final class Language extends PolyglotEngine.Language { - Language(LanguageCache info) { - super(info); - } - } // end of Language -} diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Wed Nov 11 15:59:56 2015 -0800 @@ -26,11 +26,7 @@ import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -401,11 +397,6 @@ return in; } - @Deprecated - public Reader stdIn() { - return new InputStreamReader(in); - } - /** * Standard output writer for {@link com.oracle.truffle.api.vm.PolyglotEngine} this language * is being executed in. @@ -416,11 +407,6 @@ return out; } - @Deprecated - public Writer stdOut() { - return new OutputStreamWriter(out); - } - /** * Standard error writer for {@link com.oracle.truffle.api.vm.PolyglotEngine} this language * is being executed in. @@ -431,11 +417,6 @@ return err; } - @Deprecated - public Writer stdErr() { - return new OutputStreamWriter(err); - } - public Instrumenter instrumenter() { return instrumenter; } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Wed Nov 11 15:59:56 2015 -0800 @@ -84,6 +84,11 @@ */ public static final boolean TraceASTJSON; + /** + * Forces ahead-of-time initialization. + */ + public static final boolean AOT; + private static NodeCost parseNodeInfoKind(String kind) { if (kind == null) { return null; @@ -93,7 +98,7 @@ } static { - final boolean[] values = new boolean[3]; + final boolean[] values = new boolean[4]; AccessController.doPrivileged(new PrivilegedAction() { public Void run() { values[0] = Boolean.getBoolean("truffle.TraceRewrites"); @@ -102,11 +107,13 @@ TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost")); values[1] = Boolean.getBoolean("truffle.DetailedRewriteReasons"); values[2] = Boolean.getBoolean("truffle.TraceASTJSON"); + values[3] = Boolean.getBoolean("com.oracle.truffle.aot"); return null; } }); TraceRewrites = values[0]; DetailedRewriteReasons = values[1]; TraceASTJSON = values[2]; + AOT = values[3]; } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java Wed Nov 11 15:59:56 2015 -0800 @@ -423,7 +423,7 @@ doHalt(node, vFrame.materialize()); } - public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) { + public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception) { doHalt(node, vFrame.materialize()); } @@ -481,7 +481,7 @@ doHalt(node, vFrame.materialize()); } - public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) { + public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception) { doHalt(node, vFrame.materialize()); } @@ -564,7 +564,7 @@ doHalt(node, vFrame.materialize()); } - public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) { + public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception) { doHalt(node, vFrame.materialize()); } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java Wed Nov 11 15:59:56 2015 -0800 @@ -44,7 +44,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.Debugger.BreakpointCallback; import com.oracle.truffle.api.debug.Debugger.WarningLog; import com.oracle.truffle.api.frame.VirtualFrame; @@ -368,7 +367,6 @@ } } - @SuppressWarnings("rawtypes") private void attach(Probe newProbe) { if (getState() == DISPOSED) { throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME); @@ -378,8 +376,7 @@ if (conditionSource == null) { newInstrument = instrumenter.attach(newProbe, new UnconditionalLineBreakInstrumentListener(), BREAKPOINT_NAME); } else { - final Class languageClass = Debugger.ACCESSOR.findLanguage(newProbe); - newInstrument = instrumenter.attach(newProbe, languageClass, conditionSource, this, BREAKPOINT_NAME); + newInstrument = instrumenter.attach(newProbe, conditionSource, this, BREAKPOINT_NAME, null); } instruments.add(newInstrument); changeState(isEnabled ? ENABLED : DISABLED); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Wed Nov 11 15:59:56 2015 -0800 @@ -42,7 +42,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.Debugger.BreakpointCallback; import com.oracle.truffle.api.debug.Debugger.WarningLog; import com.oracle.truffle.api.frame.VirtualFrame; @@ -330,7 +329,6 @@ } } - @SuppressWarnings("rawtypes") private void attach(Probe newProbe) { if (getState() == DISPOSED) { throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME); @@ -340,8 +338,7 @@ if (conditionSource == null) { newInstrument = instrumenter.attach(newProbe, new UnconditionalTagBreakInstrumentListener(), BREAKPOINT_NAME); } else { - final Class languageClass = Debugger.ACCESSOR.findLanguage(newProbe); - instrumenter.attach(newProbe, languageClass, conditionSource, this, BREAKPOINT_NAME); + instrumenter.attach(newProbe, conditionSource, this, BREAKPOINT_NAME, null); } instruments.add(newInstrument); changeState(isEnabled ? ENABLED : DISABLED); diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Wed Nov 11 15:59:56 2015 -0800 @@ -33,6 +33,7 @@ import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; @@ -179,7 +180,7 @@ protected boolean isInstrumentable(Object vm, Node node) { final RootNode rootNode = node.getRootNode(); Class languageClazz = findLanguage(rootNode); - TruffleLanguage language = findLanguageImpl(vm, languageClazz); + TruffleLanguage language = findLanguageImpl(vm, languageClazz, null); return isInstrumentable(node, language); } @@ -194,7 +195,7 @@ protected WrapperNode createWrapperNode(Object vm, Node node) { final RootNode rootNode = node.getRootNode(); Class languageClazz = findLanguage(rootNode); - TruffleLanguage language = findLanguageImpl(vm, languageClazz); + TruffleLanguage language = findLanguageImpl(vm, languageClazz, null); return createWrapperNode(node, language); } @@ -230,7 +231,7 @@ } @SuppressWarnings("rawtypes") - protected TruffleLanguage findLanguageImpl(Object known, Class languageClass) { + protected TruffleLanguage findLanguageImpl(Object known, Class languageClass, String mimeType) { Object vm; if (known == null) { vm = CURRENT_VM.get(); @@ -240,7 +241,7 @@ } else { vm = known; } - return SPI.findLanguageImpl(vm, languageClass); + return SPI.findLanguageImpl(vm, languageClass, mimeType); } protected Instrumenter getInstrumenter(Object known) { @@ -267,6 +268,7 @@ private static Reference previousVM = new WeakReference<>(null); private static Assumption oneVM = Truffle.getRuntime().createAssumption(); + @TruffleBoundary @SuppressWarnings("unused") protected Closeable executionStart(Object vm, int currentDepth, Debugger debugger, Source s) { vm.getClass(); @@ -280,6 +282,7 @@ } CURRENT_VM.set(vm); class ContextCloseable implements Closeable { + @TruffleBoundary @Override public void close() throws IOException { CURRENT_VM.set(prev); @@ -327,7 +330,7 @@ @SuppressWarnings("rawtypes") protected CallTarget parse(Class languageClass, Source code, Node context, String... argumentNames) throws IOException { - final TruffleLanguage truffleLanguage = findLanguageImpl(null, languageClass); + final TruffleLanguage truffleLanguage = findLanguageImpl(null, languageClass, code.getMimeType()); return parse(truffleLanguage, code, context, argumentNames); } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/EventHandlerNode.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/EventHandlerNode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/EventHandlerNode.java Wed Nov 11 15:59:56 2015 -0800 @@ -54,7 +54,7 @@ /** * An AST Node's execute method has just thrown an exception. */ - public abstract void returnExceptional(Node node, VirtualFrame vFrame, Exception exception); + public abstract void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception); /** * Gets the {@link Probe} that manages this chain of event handling. diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Wed Nov 11 15:59:56 2015 -0800 @@ -46,6 +46,7 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; +import java.util.Map; /** * Client access to instrumentation services in a Truffle execution environment. @@ -478,11 +479,71 @@ * @param listener optional client callback for results/failure notification * @param instrumentInfo instrumentInfo optional documentation about the Instrument * @return a handle for access to the binding + * @deprecated */ + @Deprecated @SuppressWarnings("rawtypes") public ProbeInstrument attach(Probe probe, Class languageClass, Source source, EvalInstrumentListener listener, String instrumentInfo) { + return attach(probe, languageClass, source, listener, instrumentInfo, new String[0], new Object[0]); + } + + /** + * Attaches a fragment of source text that is to be evaluated just before execution + * enters the location of a {@link Probe}, creating a binding called an + * {@link ProbeInstrument}. The outcome of the evaluation is reported to an optional + * {@link EvalInstrumentListener listener}, but the outcome does not affect the flow of guest + * language execution, even if the evaluation produces an exception. + *

+ * The source text is assumed to be expressed in the language identified by its associated + * {@linkplain Source#getMimeType() MIME type}, if specified, otherwise by the language + * associated with the AST location associated with the {@link Probe}. + *

+ * The source text is parsed in the lexical context of the AST location associated with the + * {@link Probe}. + *

+ * The source text executes subject to full Truffle optimization. + * + * @param probe source of AST execution events, non-null + * @param source the source code to be evaluated, non-null and non-empty, preferably with + * {@link Source#withMimeType(java.lang.String) specified mime type} that determines + * the {@link TruffleLanguage} to use when processing the source + * @param listener optional client callback for results/failure notification + * @param instrumentInfo instrumentInfo optional documentation about the Instrument + * @param parameters keys are the parameter names to pass to + * {@link TruffleLanguage#parse(com.oracle.truffle.api.source.Source, com.oracle.truffle.api.nodes.Node, java.lang.String...) + * parse} method; values will be passed to + * {@link CallTarget#call(java.lang.Object...)} returned from the parse + * method; the value can be null + * @return a handle for access to the binding + */ + public ProbeInstrument attach(Probe probe, Source source, EvalInstrumentListener listener, String instrumentInfo, Map parameters) { + final int size = parameters == null ? 0 : parameters.size(); + String[] names = new String[size]; + Object[] params = new Object[size]; + if (parameters != null) { + int index = 0; + for (Map.Entry entry : parameters.entrySet()) { + names[index] = entry.getKey(); + params[index] = entry.getValue(); + index++; + } + } + return attach(probe, null, source, listener, instrumentInfo, names, params); + } + + @SuppressWarnings("rawtypes") + private ProbeInstrument attach(Probe probe, Class languageClass, Source source, EvalInstrumentListener listener, String instrumentInfo, String[] argumentNames, + Object[] parameters) { assert probe.getInstrumenter() == this; - final EvalInstrument instrument = new EvalInstrument(languageClass, source, listener, instrumentInfo); + Class foundLanguageClass = null; + if (languageClass == null) { + if (source.getMimeType() == null) { + foundLanguageClass = ACCESSOR.findLanguage(probe); + } + } else { + foundLanguageClass = languageClass; + } + final EvalInstrument instrument = new EvalInstrument(foundLanguageClass, source, listener, instrumentInfo, argumentNames, parameters); probe.attach(instrument); return instrument; } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java Wed Nov 11 15:59:56 2015 -0800 @@ -54,10 +54,7 @@ * @see Instrumenter */ public abstract class ProbeInstrument extends Instrument { - - private static final String[] NO_ARGS = new String[0]; - - protected Probe probe = null; + Probe probe = null; /** *

Implementation Notes

@@ -223,7 +220,7 @@ } @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) { SimpleInstrument.this.simpleListener.onReturnExceptional(SimpleInstrument.this.probe, exception); if (nextInstrumentNode != null) { nextInstrumentNode.returnExceptional(node, vFrame, exception); @@ -315,7 +312,7 @@ } @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) { standardListener.onReturnExceptional(StandardInstrument.this.probe, node, vFrame, exception); if (nextInstrumentNode != null) { nextInstrumentNode.returnExceptional(node, vFrame, exception); @@ -345,13 +342,17 @@ @SuppressWarnings("rawtypes") private final Class languageClass; private final Source source; private final EvalInstrumentListener evalListener; + private final String[] names; + private final Object[] params; @SuppressWarnings("rawtypes") - EvalInstrument(Class languageClass, Source source, EvalInstrumentListener evalListener, String instrumentInfo) { + EvalInstrument(Class languageClass, Source source, EvalInstrumentListener evalListener, String instrumentInfo, String[] argumentNames, Object[] parameters) { super(instrumentInfo); this.languageClass = languageClass; this.source = source; this.evalListener = evalListener; + this.names = argumentNames; + this.params = parameters; } @Override @@ -392,7 +393,7 @@ public void enter(Node node, VirtualFrame vFrame) { if (callNode == null) { try { - final CallTarget callTarget = Instrumenter.ACCESSOR.parse(languageClass, source, node, NO_ARGS); + final CallTarget callTarget = Instrumenter.ACCESSOR.parse(languageClass, source, node, names); if (callTarget != null) { callNode = Truffle.getRuntime().createDirectCallNode(callTarget); callNode.forceInlining(); @@ -407,7 +408,7 @@ } if (callNode != null) { try { - final Object result = callNode.call(vFrame, NO_ARGS); + final Object result = callNode.call(vFrame, params); if (evalListener != null) { evalListener.onExecution(node, vFrame, result); } @@ -437,7 +438,7 @@ } @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) { if (nextInstrumentNode != null) { nextInstrumentNode.returnExceptional(node, vFrame, exception); } @@ -524,7 +525,7 @@ } @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) { if (nextInstrumentNode != null) { nextInstrumentNode.returnExceptional(node, vFrame, exception); } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Wed Nov 11 15:59:56 2015 -0800 @@ -110,7 +110,7 @@ } @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + public void returnExceptional(Node node, VirtualFrame vFrame, Throwable exception) { if (exception instanceof KillException) { throw (KillException) exception; } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java Wed Nov 11 15:59:56 2015 -0800 @@ -74,5 +74,5 @@ *

* Synchronous: Truffle execution waits until the call returns. */ - void onReturnExceptional(Probe probe, Exception exception); + void onReturnExceptional(Probe probe, Throwable exception); } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardAfterInstrumentListener.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardAfterInstrumentListener.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardAfterInstrumentListener.java Wed Nov 11 15:59:56 2015 -0800 @@ -68,5 +68,5 @@ *

* Synchronous: Truffle execution waits until the call returns. */ - void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception); + void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception); } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java Wed Nov 11 15:59:56 2015 -0800 @@ -74,5 +74,5 @@ *

* Synchronous: Truffle execution waits until the call returns. */ - void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception); + void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception); } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java Wed Nov 11 15:59:56 2015 -0800 @@ -41,6 +41,6 @@ public void onReturnValue(Probe probe, Object result) { } - public void onReturnExceptional(Probe probe, Exception exception) { + public void onReturnExceptional(Probe probe, Throwable exception) { } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java Wed Nov 11 15:59:56 2015 -0800 @@ -44,7 +44,6 @@ public void onReturnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) { } - public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) { + public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Throwable exception) { } - } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Wed Nov 11 15:59:56 2015 -0800 @@ -99,21 +99,6 @@ public abstract void forceInlining(); /** - * Returns true if the runtime system has decided to inline this call-site. If the - * {@link DirectCallNode} was forced to inline then this does not necessarily mean that the - * {@link DirectCallNode} is really going to be inlined. This depends on whether or not the - * runtime system supports inlining. The runtime system may also decide to not inline calls - * which were forced to inline. - * - * @deprecated we do not expose this information any longer. returns always false. - */ - @SuppressWarnings("static-method") - @Deprecated - public final boolean isInlined() { - return false; - } - - /** * Returns true if the runtime system supports cloning and the {@link RootNode} * returns true in {@link RootNode#isCloningAllowed()}. * diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Wed Nov 11 15:59:56 2015 -0800 @@ -24,111 +24,243 @@ */ package com.oracle.truffle.api.nodes; -import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind; import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.StringWriter; +import java.io.OutputStream; +import java.io.PrintStream; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.net.Socket; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; + +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import com.oracle.truffle.api.TruffleOptions; +import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind; /** * Utility class for creating output for the ideal graph visualizer. */ -public class GraphPrintVisitor { +public class GraphPrintVisitor implements Closeable { public static final String GraphVisualizerAddress = "127.0.0.1"; public static final int GraphVisualizerPort = 4444; + private static final String DEFAULT_GRAPH_NAME = "truffle tree"; - private Document dom; - private Map nodeMap; - private List edgeList; - private Map prevNodeMap; + private Map nodeMap; + private List edgeList; + private Map prevNodeMap; private int id; - private Element graphDocument; - private Element groupElement; - private Element graphElement; - private Element nodesElement; - private Element edgesElement; + private Impl xmlstream; + private OutputStream outputStream; + private int openGroupCount; + private int openGraphCount; + private String currentGraphName; + + private static class NodeElement { + private final int id; + private final Map properties; + + public NodeElement(int id) { + super(); + this.id = id; + this.properties = new LinkedHashMap<>(); + } + + public int getId() { + return id; + } + + public Map getProperties() { + return properties; + } + } + + private static class EdgeElement { + private final NodeElement from; + private final NodeElement to; + private final int index; + private final String label; + + public EdgeElement(NodeElement from, NodeElement to, int index, String label) { + this.from = from; + this.to = to; + this.index = index; + this.label = label; + } + + public NodeElement getFrom() { + return from; + } + + public NodeElement getTo() { + return to; + } + + public int getIndex() { + return index; + } + + public String getLabel() { + return label; + } + } + + private static class Impl { + private static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance(); + private final XMLStreamWriter xmlstream; + + protected Impl(OutputStream outputStream) { + try { + this.xmlstream = XML_OUTPUT_FACTORY.createXMLStreamWriter(outputStream); + } catch (XMLStreamException | FactoryConfigurationError e) { + throw new RuntimeException(e); + } + } + + public void writeStartDocument() { + try { + xmlstream.writeStartDocument(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + public void writeEndDocument() { + try { + xmlstream.writeEndDocument(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + public void writeStartElement(String name) { + try { + xmlstream.writeStartElement(name); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + public void writeEndElement() { + try { + xmlstream.writeEndElement(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + public void writeAttribute(String name, String value) { + try { + xmlstream.writeAttribute(name, value); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + public void writeCharacters(String text) { + try { + xmlstream.writeCharacters(text); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + public void flush() { + try { + xmlstream.flush(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + public void close() { + try { + xmlstream.close(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + } public GraphPrintVisitor() { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - try { - DocumentBuilder db = dbf.newDocumentBuilder(); + this(new ByteArrayOutputStream()); + } - dom = db.newDocument(); - } catch (ParserConfigurationException ex) { - throw new RuntimeException(ex); + public GraphPrintVisitor(OutputStream outputStream) { + this.outputStream = outputStream; + this.xmlstream = new Impl(outputStream); + this.xmlstream.writeStartDocument(); + this.xmlstream.writeStartElement("graphDocument"); + } + + private void ensureOpen() { + if (xmlstream == null) { + throw new IllegalStateException("printer is closed"); } - - graphDocument = dom.createElement("graphDocument"); - dom.appendChild(graphDocument); } public GraphPrintVisitor beginGroup(String groupName) { - groupElement = dom.createElement("group"); - graphDocument.appendChild(groupElement); - Element properties = dom.createElement("properties"); - groupElement.appendChild(properties); + ensureOpen(); + maybeEndGraph(); + openGroupCount++; + xmlstream.writeStartElement("group"); + xmlstream.writeStartElement("properties"); if (!groupName.isEmpty()) { // set group name - Element propName = dom.createElement("p"); - propName.setAttribute("name", "name"); - propName.setTextContent(groupName); - properties.appendChild(propName); + xmlstream.writeStartElement("p"); + xmlstream.writeAttribute("name", "name"); + xmlstream.writeCharacters(groupName); + xmlstream.writeEndElement(); } + xmlstream.writeEndElement(); // properties + // forget old nodes - nodeMap = prevNodeMap = null; - edgeList = null; + prevNodeMap = null; + nodeMap = new IdentityHashMap<>(); + edgeList = new ArrayList<>(); + + return this; + } + + public GraphPrintVisitor endGroup() { + ensureOpen(); + if (openGroupCount <= 0) { + throw new IllegalArgumentException("no open group"); + } + maybeEndGraph(); + openGroupCount--; + + xmlstream.writeEndElement(); // group return this; } public GraphPrintVisitor beginGraph(String graphName) { - if (null == groupElement) { - beginGroup(""); - } else if (null != prevNodeMap) { - // TODO: difference (create removeNode,removeEdge elements) + ensureOpen(); + if (openGroupCount == 0) { + beginGroup(graphName); } + maybeEndGraph(); + openGraphCount++; - graphElement = dom.createElement("graph"); - groupElement.appendChild(graphElement); - Element properties = dom.createElement("properties"); - graphElement.appendChild(properties); - nodesElement = dom.createElement("nodes"); - graphElement.appendChild(nodesElement); - edgesElement = dom.createElement("edges"); - graphElement.appendChild(edgesElement); - - // set graph name - Element propName = dom.createElement("p"); - propName.setAttribute("name", "name"); - propName.setTextContent(graphName); - properties.appendChild(propName); + this.currentGraphName = graphName; // save old nodes prevNodeMap = nodeMap; @@ -138,92 +270,156 @@ return this; } + private void maybeEndGraph() { + if (openGraphCount > 0) { + endGraph(); + assert openGraphCount == 0; + } + } + + public GraphPrintVisitor endGraph() { + ensureOpen(); + if (openGraphCount <= 0) { + throw new IllegalArgumentException("no open graph"); + } + openGraphCount--; + + xmlstream.writeStartElement("graph"); + + xmlstream.writeStartElement("properties"); + + // set graph name + xmlstream.writeStartElement("p"); + xmlstream.writeAttribute("name", "name"); + xmlstream.writeCharacters(currentGraphName); + xmlstream.writeEndElement(); + + xmlstream.writeEndElement(); // properties + + xmlstream.writeStartElement("nodes"); + writeNodes(); + xmlstream.writeEndElement(); // nodes + + xmlstream.writeStartElement("edges"); + writeEdges(); + xmlstream.writeEndElement(); // edges + + xmlstream.writeEndElement(); // graph + + xmlstream.flush(); + + return this; + } + + private void writeNodes() { + for (NodeElement node : nodeMap.values()) { + xmlstream.writeStartElement("node"); + xmlstream.writeAttribute("id", String.valueOf(node.getId())); + + xmlstream.writeStartElement("properties"); + for (Map.Entry property : node.getProperties().entrySet()) { + xmlstream.writeStartElement("p"); + xmlstream.writeAttribute("name", property.getKey()); + xmlstream.writeCharacters(safeToString(property.getValue())); + xmlstream.writeEndElement(); // p + } + xmlstream.writeEndElement(); // properties + + xmlstream.writeEndElement(); // node + } + } + + private void writeEdges() { + for (EdgeElement edge : edgeList) { + xmlstream.writeStartElement("edge"); + + xmlstream.writeAttribute("from", String.valueOf(edge.getFrom().getId())); + xmlstream.writeAttribute("to", String.valueOf(edge.getTo().getId())); + xmlstream.writeAttribute("index", String.valueOf(edge.getIndex())); + if (edge.getLabel() != null) { + xmlstream.writeAttribute("label", edge.getLabel()); + } + + xmlstream.writeEndElement(); // edge + } + } + @Override public String toString() { - if (null != dom) { - try { - Transformer tr = TransformerFactory.newInstance().newTransformer(); - tr.setOutputProperty(OutputKeys.INDENT, "yes"); - tr.setOutputProperty(OutputKeys.METHOD, "xml"); - tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - - StringWriter strWriter = new StringWriter(); - tr.transform(new DOMSource(dom), new StreamResult(strWriter)); - return strWriter.toString(); - } catch (TransformerException e) { - e.printStackTrace(); - } + if (outputStream instanceof ByteArrayOutputStream) { + return new String(((ByteArrayOutputStream) outputStream).toByteArray(), Charset.forName("UTF-8")); } - return ""; + return super.toString(); } public void printToFile(File f) { - try { - Transformer tr = TransformerFactory.newInstance().newTransformer(); - tr.setOutputProperty(OutputKeys.INDENT, "yes"); - tr.setOutputProperty(OutputKeys.METHOD, "xml"); - tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - - tr.transform(new DOMSource(dom), new StreamResult(new FileOutputStream(f))); - } catch (TransformerException | FileNotFoundException e) { - e.printStackTrace(); + close(); + if (outputStream instanceof ByteArrayOutputStream) { + try (OutputStream os = new FileOutputStream(f)) { + os.write(((ByteArrayOutputStream) outputStream).toByteArray()); + } catch (IOException e) { + e.printStackTrace(); + } } } public void printToSysout() { - try { - Transformer tr = TransformerFactory.newInstance().newTransformer(); - tr.setOutputProperty(OutputKeys.INDENT, "yes"); - tr.setOutputProperty(OutputKeys.METHOD, "xml"); - tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - - tr.transform(new DOMSource(dom), new StreamResult(System.out)); - } catch (TransformerException e) { - e.printStackTrace(); + close(); + if (outputStream instanceof ByteArrayOutputStream) { + PrintStream out = System.out; + out.println(toString()); } } public void printToNetwork(boolean ignoreErrors) { - try { - Transformer tr = TransformerFactory.newInstance().newTransformer(); - tr.setOutputProperty(OutputKeys.METHOD, "xml"); - - Socket socket = new Socket(GraphVisualizerAddress, GraphVisualizerPort); - BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000); - tr.transform(new DOMSource(dom), new StreamResult(stream)); - } catch (TransformerException | IOException e) { + close(); + try (Socket socket = new Socket(GraphVisualizerAddress, GraphVisualizerPort); BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream(), 0x4000)) { + os.write(((ByteArrayOutputStream) outputStream).toByteArray()); + } catch (IOException e) { if (!ignoreErrors) { e.printStackTrace(); } } } - private String nextId() { - return String.valueOf(id++); + public void close() { + if (xmlstream == null) { + return; + } + while (openGroupCount > 0) { + endGroup(); + } + assert openGraphCount == 0 && openGroupCount == 0; + + xmlstream.writeEndElement(); // graphDocument + xmlstream.writeEndDocument(); + xmlstream.flush(); + xmlstream.close(); + xmlstream = null; } - private String oldOrNextId(Object node) { + private int nextId() { + return id++; + } + + private int oldOrNextId(Object node) { if (null != prevNodeMap && prevNodeMap.containsKey(node)) { - Element nodeElem = prevNodeMap.get(node); - return nodeElem.getAttribute("id"); + NodeElement nodeElem = prevNodeMap.get(node); + return nodeElem.getId(); } else { return nextId(); } } - protected Element getElementByObject(Object op) { - return nodeMap.get(op); + protected NodeElement getElementByObject(Object obj) { + return nodeMap.get(obj); } protected void createElementForNode(Object node) { boolean exists = nodeMap.containsKey(node); - if (!exists || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) { - Element nodeElem = dom.createElement("node"); - nodeElem.setAttribute("id", !exists ? oldOrNextId(node) : nextId()); - nodeMap.put(node, nodeElem); - Element properties = dom.createElement("properties"); - nodeElem.appendChild(properties); - nodesElement.appendChild(nodeElem); + if (!exists) { + int nodeId = !exists ? oldOrNextId(node) : nextId(); + nodeMap.put(node, new NodeElement(nodeId)); setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", "")); NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class); @@ -241,33 +437,9 @@ } } - private Element getPropertyElement(Object node, String propertyName) { - Element nodeElem = getElementByObject(node); - Element propertiesElem = (Element) nodeElem.getElementsByTagName("properties").item(0); - if (propertiesElem == null) { - return null; - } - - NodeList propList = propertiesElem.getElementsByTagName("p"); - for (int i = 0; i < propList.getLength(); i++) { - Element p = (Element) propList.item(i); - if (propertyName.equals(p.getAttribute("name"))) { - return p; - } - } - return null; - } - protected void setNodeProperty(Object node, String propertyName, Object value) { - Element nodeElem = getElementByObject(node); - Element propElem = getPropertyElement(node, propertyName); // if property exists, replace - // its value - if (null == propElem) { // if property doesn't exist, create one - propElem = dom.createElement("p"); - propElem.setAttribute("name", propertyName); - nodeElem.getElementsByTagName("properties").item(0).appendChild(propElem); - } - propElem.setTextContent(String.valueOf(value)); + NodeElement nodeElem = getElementByObject(node); + nodeElem.getProperties().put(propertyName, value); } private void copyDebugProperties(Node node) { @@ -278,11 +450,11 @@ } private void readNodeProperties(Node node) { - NodeFieldAccessor[] fields = node.getNodeClass().getFields(); + NodeFieldAccessor[] fields = NodeClass.get(node).getFields(); for (NodeFieldAccessor field : fields) { if (field.getKind() == NodeFieldKind.DATA) { String key = field.getName(); - if (getPropertyElement(node, key) == null) { + if (!getElementByObject(node).getProperties().containsKey(key)) { Object value = field.loadValue(node); setNodeProperty(node, key, value); } @@ -291,71 +463,66 @@ } protected void connectNodes(Object a, Object b, String label) { - if (nodeMap.get(a) == null || nodeMap.get(b) == null) { + NodeElement fromNode = getElementByObject(a); + NodeElement toNode = getElementByObject(b); + if (fromNode == null || toNode == null) { return; } - String fromId = nodeMap.get(a).getAttribute("id"); - String toId = nodeMap.get(b).getAttribute("id"); - // count existing to-edges int count = 0; - for (Element e : edgeList) { - if (e.getAttribute("to").equals(toId)) { + for (EdgeElement e : edgeList) { + if (e.getTo() == toNode) { ++count; } } - Element edgeElem = dom.createElement("edge"); - edgeElem.setAttribute("from", fromId); - edgeElem.setAttribute("to", toId); - edgeElem.setAttribute("index", String.valueOf(count)); - if (label != null) { - edgeElem.setAttribute("label", label); - } - edgesElement.appendChild(edgeElem); - edgeList.add(edgeElem); + edgeList.add(new EdgeElement(fromNode, toNode, count, label)); } public GraphPrintVisitor visit(Object node) { - if (null == graphElement) { - beginGraph("truffle tree"); + if (openGraphCount == 0) { + beginGraph(DEFAULT_GRAPH_NAME); } // if node is visited once again, skip - if (getElementByObject(node) != null && NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) == null) { + if (getElementByObject(node) != null) { return this; } // respect node's custom handler - if (NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) { - Class customHandlerClass = NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler(); - try { - GraphPrintHandler customHandler = customHandlerClass.newInstance(); - customHandler.visit(node, new GraphPrintAdapter()); - } catch (InstantiationException | IllegalAccessException e) { - assert false : e; - } + if (!TruffleOptions.AOT && NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) { + visit(node, createGraphPrintHandlerFromClass(NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler())); } else if (NodeUtil.findAnnotation(node.getClass(), NullGraphPrintHandler.class) != null) { // ignore } else { - // default handler - createElementForNode(node); - - if (node instanceof Node) { - for (Map.Entry child : findNamedNodeChildren((Node) node).entrySet()) { - visit(child.getValue()); - connectNodes(node, child.getValue(), child.getKey()); - } - } + visit(node, new DefaultGraphPrintHandler()); } return this; } + public GraphPrintVisitor visit(Object node, GraphPrintHandler handler) { + if (openGraphCount == 0) { + beginGraph(DEFAULT_GRAPH_NAME); + } + + handler.visit(node, new GraphPrintAdapter()); + + return this; + } + + private static GraphPrintHandler createGraphPrintHandlerFromClass(Class customHandlerClass) { + try { + return customHandlerClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new AssertionError(e); + } + } + private static LinkedHashMap findNamedNodeChildren(Node node) { LinkedHashMap nodes = new LinkedHashMap<>(); - NodeClass nodeClass = node.getNodeClass(); + NodeClass nodeClass = NodeClass.get(node); for (NodeFieldAccessor field : nodeClass.getFields()) { NodeFieldKind kind = field.getKind(); @@ -379,6 +546,14 @@ return nodes; } + private static String safeToString(Object value) { + try { + return String.valueOf(value); + } catch (Throwable ex) { + return value.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(value)); + } + } + public class GraphPrintAdapter { public void createElementForNode(Object node) { @@ -389,27 +564,43 @@ GraphPrintVisitor.this.visit(node); } + public void visit(Object node, GraphPrintHandler handler) { + GraphPrintVisitor.this.visit(node, handler); + } + public void connectNodes(Object node, Object child) { GraphPrintVisitor.this.connectNodes(node, child, null); } + public void connectNodes(Object node, Object child, String label) { + GraphPrintVisitor.this.connectNodes(node, child, label); + } + public void setNodeProperty(Object node, String propertyName, Object value) { GraphPrintVisitor.this.setNodeProperty(node, propertyName, value); } + + public boolean visited(Object node) { + return GraphPrintVisitor.this.getElementByObject(node) != null; + } } public interface GraphPrintHandler { - void visit(Object node, GraphPrintAdapter gPrinter); + void visit(Object node, GraphPrintAdapter printer); } - public interface ChildSupplier { + private static final class DefaultGraphPrintHandler implements GraphPrintHandler { + public void visit(Object node, GraphPrintAdapter printer) { + printer.createElementForNode(node); - /** Supplies an additional child if available. */ - Object startNode(Object callNode); - - void endNode(Object callNode); - + if (node instanceof Node) { + for (Map.Entry child : findNamedNodeChildren((Node) node).entrySet()) { + printer.visit(child.getValue()); + printer.connectNodes(node, child.getValue(), child.getKey()); + } + } + } } @Retention(RetentionPolicy.RUNTIME) @@ -423,14 +614,4 @@ @Target(ElementType.TYPE) public @interface NullGraphPrintHandler { } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - public @interface GraphDuplicate { - } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface HiddenField { - } } diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Wed Nov 11 15:59:56 2015 -0800 @@ -392,16 +392,6 @@ } /** - * This method must never be called. It enforces that {@link Object#clone} is not directly - * called by subclasses. Use the {@link #copy()} method instead. - */ - @Override - @Deprecated - protected final Object clone() throws CloneNotSupportedException { - throw new IllegalStateException("This method should never be called, use the copy method instead!"); - } - - /** * Get the root node of the tree a node belongs to. * * @return the {@link RootNode} or {@code null} if there is none. diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java Wed Nov 11 15:59:56 2015 -0800 @@ -53,6 +53,8 @@ } }; + private static final NodeFieldAccessor[] EMPTY_NODE_FIELD_ARRAY = new NodeFieldAccessor[0]; + // The comprehensive list of all fields. private final NodeFieldAccessor[] fields; // Separate arrays for the frequently accessed fields. @@ -68,11 +70,11 @@ return nodeClasses.get(clazz); } - public static NodeClass get(Node clazz) { - return clazz.getNodeClass(); + public static NodeClass get(Node node) { + return node.getNodeClass(); } - public NodeClass(Class clazz) { + NodeClass(Class clazz) { List fieldsList = new ArrayList<>(); NodeFieldAccessor parentFieldTmp = null; NodeFieldAccessor nodeClassFieldTmp = null; @@ -115,12 +117,12 @@ throw new AssertionError("parent field not found"); } - this.fields = fieldsList.toArray(new NodeFieldAccessor[fieldsList.size()]); + this.fields = fieldsList.toArray(EMPTY_NODE_FIELD_ARRAY); this.nodeClassField = nodeClassFieldTmp; this.parentField = parentFieldTmp; - this.childFields = childFieldList.toArray(new NodeFieldAccessor[childFieldList.size()]); - this.childrenFields = childrenFieldList.toArray(new NodeFieldAccessor[childrenFieldList.size()]); - this.cloneableFields = cloneableFieldList.toArray(new NodeFieldAccessor[cloneableFieldList.size()]); + this.childFields = childFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); + this.childrenFields = childrenFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); + this.cloneableFields = cloneableFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); this.clazz = clazz; } diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Wed Nov 11 15:59:56 2015 -0800 @@ -421,9 +421,11 @@ if (clazz.getAnnotation(annotationClass) != null) { return clazz.getAnnotation(annotationClass); } else { - for (Class intf : clazz.getInterfaces()) { - if (intf.getAnnotation(annotationClass) != null) { - return intf.getAnnotation(annotationClass); + if (!TruffleOptions.AOT) { + for (Class intf : clazz.getInterfaces()) { + if (intf.getAnnotation(annotationClass) != null) { + return intf.getAnnotation(annotationClass); + } } } if (clazz.getSuperclass() != null) { diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Wed Nov 11 15:59:56 2015 -0800 @@ -49,33 +49,6 @@ @CompilationFinal private FrameDescriptor frameDescriptor; /** - * @deprecated each RootNode should be associated with a {@link TruffleLanguage} use constructor - * that allows you to specify it. This method will be removed on Aug 15, 2015. - */ - @Deprecated - protected RootNode() { - this(null, null, null, false); - } - - /** - * @deprecated each RootNode should be associated with a {@link TruffleLanguage} use constructor - * that allows you to specify it. This method will be removed on Aug 15, 2015. - */ - @Deprecated - protected RootNode(SourceSection sourceSection) { - this(null, sourceSection, null, false); - } - - /** - * @deprecated each RootNode should be associated with a {@link TruffleLanguage} use constructor - * that allows you to specify it. This method will be removed on Aug 15, 2015. - */ - @Deprecated - protected RootNode(SourceSection sourceSection, FrameDescriptor frameDescriptor) { - this(null, sourceSection, frameDescriptor, false); - } - - /** * Creates new root node. Each {@link RootNode} is associated with a particular language - if * the root node represents a method it is assumed the method is written in such language. *

diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java Wed Nov 11 15:59:56 2015 -0800 @@ -24,10 +24,11 @@ */ package com.oracle.truffle.api.utilities; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; -import java.util.concurrent.atomic.AtomicReference; /** * Holds an {@link Assumption}, and knows how to recreate it with the same properties on @@ -39,22 +40,24 @@ public class CyclicAssumption { private final String name; - private final AtomicReference assumption; + private volatile Assumption assumption; + + private static final AtomicReferenceFieldUpdater ASSUMPTION_UPDATER = AtomicReferenceFieldUpdater.newUpdater(CyclicAssumption.class, Assumption.class, "assumption"); public CyclicAssumption(String name) { this.name = name; - this.assumption = new AtomicReference<>(Truffle.getRuntime().createAssumption(name)); + this.assumption = Truffle.getRuntime().createAssumption(name); } @TruffleBoundary public void invalidate() { Assumption newAssumption = Truffle.getRuntime().createAssumption(name); - Assumption oldAssumption = assumption.getAndSet(newAssumption); + Assumption oldAssumption = ASSUMPTION_UPDATER.getAndSet(this, newAssumption); oldAssumption.invalidate(); } public Assumption getAssumption() { - return assumption.get(); + return assumption; } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java --- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java Wed Nov 11 15:59:56 2015 -0800 @@ -23,6 +23,7 @@ package com.oracle.truffle.dsl.processor.java.compiler; import com.oracle.truffle.dsl.processor.java.ElementUtils; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -31,6 +32,7 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; + import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; @@ -47,13 +49,21 @@ } } + /** + * @see "https://bugs.openjdk.java.net/browse/JDK-8039214" + */ + @SuppressWarnings("unused") + private static List newElementList(List src) { + List workaround = new ArrayList(src); + return workaround; + } + public List getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) { - return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type))); - + return sortBySourceOrder(newElementList(environment.getElementUtils().getAllMembers(type))); } public List getEnclosedElementsInDeclarationOrder(TypeElement type) { - return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements())); + return sortBySourceOrder(newElementList(type.getEnclosedElements())); } private static List sortBySourceOrder(List elements) { diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java --- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Wed Nov 11 15:59:56 2015 -0800 @@ -72,20 +72,21 @@ } public boolean isCacheBoundByGuard(CacheExpression cacheExpression) { + VariableElement cachedVariable = cacheExpression.getParameter().getVariableElement(); + for (GuardExpression expression : getGuards()) { - if (expression.getExpression().findBoundVariableElements().contains(cacheExpression.getParameter().getVariableElement())) { + if (expression.getExpression().findBoundVariableElements().contains(cachedVariable)) { return true; } } - // check all next binding caches if they are bound by guard - Set boundVariables = cacheExpression.getExpression().findBoundVariableElements(); + // check all next binding caches if they are bound to a guard and use this cache variable boolean found = false; for (CacheExpression expression : getCaches()) { if (cacheExpression == expression) { found = true; } else if (found) { - if (boundVariables.contains(expression.getParameter().getVariableElement())) { + if (expression.getExpression().findBoundVariableElements().contains(cachedVariable)) { if (isCacheBoundByGuard(expression)) { return true; } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java --- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Wed Nov 11 15:59:56 2015 -0800 @@ -66,6 +66,7 @@ import com.oracle.truffle.dsl.processor.model.SpecializationThrowsData; import com.oracle.truffle.dsl.processor.model.TemplateMethod; import com.oracle.truffle.dsl.processor.model.TypeSystemData; + import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; @@ -79,6 +80,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; + import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; @@ -304,9 +306,7 @@ } private List loadMembers(TypeElement templateType) { - List members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); - - return members; + return newElementList(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); } private boolean containsSpecializations(List elements) { @@ -1276,7 +1276,7 @@ private static List filterNotAccessibleElements(TypeElement templateType, List elements) { String packageName = ElementUtils.getPackageName(templateType); - List filteredElements = new ArrayList<>(elements); + List filteredElements = newElementList(elements); for (Element element : elements) { Modifier visibility = ElementUtils.getVisibility(element.getModifiers()); if (visibility == Modifier.PRIVATE) { @@ -1599,6 +1599,15 @@ } } + /** + * @see "https://bugs.openjdk.java.net/browse/JDK-8039214" + */ + @SuppressWarnings("unused") + private static List newElementList(List src) { + List workaround = new ArrayList(src); + return workaround; + } + private static void verifyMissingAbstractMethods(NodeData nodeData, List originalElements) { if (!nodeData.needsFactory()) { // missing abstract methods only needs to be implemented @@ -1606,7 +1615,7 @@ return; } - List elements = new ArrayList<>(originalElements); + List elements = newElementList(originalElements); Set unusedElements = new HashSet<>(elements); for (ExecutableElement method : nodeData.getAllTemplateMethods()) { unusedElements.remove(method); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java --- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java Wed Nov 11 15:59:56 2015 -0800 @@ -32,6 +32,7 @@ import com.oracle.truffle.dsl.processor.model.TypeCastData; import com.oracle.truffle.dsl.processor.model.TypeCheckData; import com.oracle.truffle.dsl.processor.model.TypeSystemData; + import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; @@ -40,6 +41,7 @@ import java.util.List; import java.util.Map; import java.util.Set; + import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; @@ -60,6 +62,15 @@ return TypeSystem.class; } + /** + * @see "https://bugs.openjdk.java.net/browse/JDK-8039214" + */ + @SuppressWarnings("unused") + private static List newElementList(List src) { + List workaround = new ArrayList(src); + return workaround; + } + @Override protected TypeSystemData parse(Element element, AnnotationMirror mirror) { TypeElement templateType = (TypeElement) element; @@ -94,7 +105,7 @@ verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); - List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); + List elements = newElementList(context.getEnvironment().getElementUtils().getAllMembers(templateType)); List implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements); List casts = new TypeCastParser(context, typeSystem).parse(elements); List checks = new TypeCheckParser(context, typeSystem).parse(elements); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java Wed Nov 11 15:59:56 2015 -0800 @@ -22,20 +22,74 @@ */ package com.oracle.truffle.object; -import com.oracle.truffle.object.debug.JSONShapeVisitor; +import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; +import java.nio.file.Paths; import java.util.Collection; +import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; +import com.oracle.truffle.api.nodes.GraphPrintVisitor; +import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.api.object.Property; +import com.oracle.truffle.object.debug.GraphvizShapeVisitor; +import com.oracle.truffle.object.debug.IGVShapeVisitor; +import com.oracle.truffle.object.debug.JSONShapeVisitor; +import com.oracle.truffle.object.debug.ShapeProfiler; + class Debug { private static Collection allShapes; - static void registerShape(ShapeImpl newShape) { + static void trackShape(ShapeImpl newShape) { allShapes.add(newShape); } + static void trackObject(DynamicObject obj) { + ShapeProfiler.getInstance().track(obj); + } + + static Iterable getAllShapes() { + return allShapes; + } + + static String dumpObject(DynamicObject object, int level, int levelStop) { + List properties = object.getShape().getPropertyListInternal(true); + StringBuilder sb = new StringBuilder(properties.size() * 10); + sb.append("{\n"); + for (Property property : properties) { + indent(sb, level + 1); + + sb.append(property.getKey()); + sb.append('[').append(property.getLocation()).append(']'); + Object value = property.get(object, false); + if (value instanceof DynamicObject) { + if (level < levelStop) { + value = dumpObject((DynamicObject) value, level + 1, levelStop); + } else { + value = value.toString(); + } + } + sb.append(": "); + sb.append(value); + if (property != properties.get(properties.size() - 1)) { + sb.append(","); + } + sb.append("\n"); + } + indent(sb, level); + sb.append("}"); + return sb.toString(); + } + + private static StringBuilder indent(StringBuilder sb, int level) { + for (int i = 0; i < level; i++) { + sb.append(' '); + } + return sb; + } + static { if (ObjectStorageOptions.DumpShapes) { allShapes = new ConcurrentLinkedQueue<>(); @@ -44,10 +98,36 @@ if (ObjectStorageOptions.DumpShapes) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { public void run() { - try (PrintWriter out = new PrintWriter("shapes.json", "UTF-8")) { + try { + if (ObjectStorageOptions.DumpShapesDOT) { + dumpDOT(); + } + if (ObjectStorageOptions.DumpShapesJSON) { + dumpJSON(); + } + if (ObjectStorageOptions.DumpShapesIGV) { + dumpIGV(); + } + } catch (FileNotFoundException | UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + private void dumpDOT() throws FileNotFoundException, UnsupportedEncodingException { + try (PrintWriter out = new PrintWriter(getOutputFile("dot"), "UTF-8")) { + GraphvizShapeVisitor visitor = new GraphvizShapeVisitor(); + for (ShapeImpl shape : getAllShapes()) { + shape.accept(visitor); + } + out.println(visitor); + } + } + + private void dumpJSON() throws FileNotFoundException, UnsupportedEncodingException { + try (PrintWriter out = new PrintWriter(getOutputFile("json"), "UTF-8")) { out.println("{\"shapes\": ["); boolean first = true; - for (ShapeImpl shape : allShapes) { + for (ShapeImpl shape : getAllShapes()) { if (!first) { out.println(","); } @@ -58,9 +138,37 @@ out.println(); } out.println("]}"); - } catch (FileNotFoundException | UnsupportedEncodingException e) { - throw new RuntimeException(e); + } + } + + private void dumpIGV() { + GraphPrintVisitor printer = new GraphPrintVisitor(); + printer.beginGroup("shapes"); + IGVShapeVisitor visitor = new IGVShapeVisitor(printer); + for (ShapeImpl shape : getAllShapes()) { + if (isRootShape(shape)) { + printer.beginGraph(DebugShapeVisitor.getId(shape)); + shape.accept(visitor); + printer.endGraph(); + } } + printer.beginGraph("all shapes"); + for (ShapeImpl shape : getAllShapes()) { + if (isRootShape(shape)) { + shape.accept(visitor); + } + } + printer.endGraph(); + printer.endGroup(); + printer.printToNetwork(false); + } + + private boolean isRootShape(ShapeImpl shape) { + return shape.getParent() == null; + } + + private File getOutputFile(String extension) { + return Paths.get(ObjectStorageOptions.DumpShapesPath, "shapes." + extension).toFile(); } })); } diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java Wed Nov 11 15:59:56 2015 -0800 @@ -29,8 +29,6 @@ import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.object.Locations.ValueLocation; -import com.oracle.truffle.object.debug.ShapeProfiler; -import java.util.List; public abstract class DynamicObjectImpl extends DynamicObject implements Cloneable { private ShapeImpl shape; @@ -43,7 +41,7 @@ setShape(shape); if (ObjectStorageOptions.Profile) { - trackObject(this); + Debug.trackObject(this); } } @@ -207,39 +205,7 @@ } public String debugDump(int level, int levelStop) { - List properties = this.getShape().getPropertyListInternal(true); - StringBuilder sb = new StringBuilder(properties.size() * 10); - sb.append("{\n"); - for (Property property : properties) { - indent(sb, level + 1); - - sb.append(property.getKey()); - sb.append('[').append(property.getLocation()).append(']'); - Object value = property.get(this, false); - if (value instanceof DynamicObjectImpl) { - if (level < levelStop) { - value = ((DynamicObjectImpl) value).debugDump(level + 1, levelStop); - } else { - value = value.toString(); - } - } - sb.append(": "); - sb.append(value); - if (property != properties.get(properties.size() - 1)) { - sb.append(","); - } - sb.append("\n"); - } - indent(sb, level); - sb.append("}"); - return sb.toString(); - } - - private static StringBuilder indent(StringBuilder sb, int level) { - for (int i = 0; i < level; i++) { - sb.append(' '); - } - return sb; + return Debug.dumpObject(this, level, levelStop); } @Override @@ -333,10 +299,6 @@ return getShape().getLayout().getStrategy().updateShape(this); } - private static void trackObject(DynamicObject obj) { - ShapeProfiler.getInstance().track(obj); - } - @Override public final DynamicObject copy(Shape currentShape) { return cloneWithShape(currentShape); @@ -344,6 +306,6 @@ @Override public ForeignAccess getForeignAccess() { - return getShape().getForeignAccessFactory(); + return getShape().getForeignAccessFactory(this); } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java Wed Nov 11 15:59:56 2015 -0800 @@ -40,7 +40,11 @@ // Debug options (should be final) public static final boolean DebugCounters = booleanOption(OPTION_PREFIX + "DebugCounters", true); public static final boolean TraceReshape = booleanOption(OPTION_PREFIX + "TraceReshape", false); - public static final boolean DumpShapes = booleanOption(OPTION_PREFIX + "DumpShapes", false); + public static final boolean DumpShapesDOT = booleanOption(OPTION_PREFIX + "DumpShapesDOT", false); + public static final boolean DumpShapesJSON = booleanOption(OPTION_PREFIX + "DumpShapesJSON", false); + public static final boolean DumpShapesIGV = booleanOption(OPTION_PREFIX + "DumpShapesIGV", false); + public static final boolean DumpShapes = DumpShapesDOT || DumpShapesJSON || DumpShapesIGV; + public static final String DumpShapesPath = System.getProperty(OPTION_PREFIX + "DumpShapesPath", ""); public static final boolean Profile = booleanOption(OPTION_PREFIX + "Profile", false); public static final int ProfileTopResults = Integer.getInteger(OPTION_PREFIX + "ProfileTopResults", -1); diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Wed Nov 11 15:59:56 2015 -0800 @@ -154,7 +154,9 @@ this.extraData = objectType.createShapeData(this); shapeCount.inc(); - debugRegisterShape(this); + if (ObjectStorageOptions.DumpShapes) { + Debug.trackShape(this); + } } protected ShapeImpl(Layout layout, ShapeImpl parent, ObjectType operations, Object sharedData, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) { @@ -1126,12 +1128,6 @@ } } - private static void debugRegisterShape(ShapeImpl newShape) { - if (ObjectStorageOptions.DumpShapes) { - Debug.registerShape(newShape); - } - } - /** * Match all filter. */ @@ -1152,7 +1148,7 @@ private static final DebugCounter shapeCacheHitCount = DebugCounter.create("Shape cache hits"); private static final DebugCounter shapeCacheMissCount = DebugCounter.create("Shape cache misses"); - public ForeignAccess getForeignAccessFactory() { - return getObjectType().getForeignAccessFactory(); + public ForeignAccess getForeignAccessFactory(DynamicObject object) { + return getObjectType().getForeignAccessFactory(object); } } diff -r ad180d3d4bd7 -r 163fdf64587d 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 Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java Wed Nov 11 15:59:56 2015 -0800 @@ -42,7 +42,7 @@ @Override public GraphvizShapeVisitor visitShape(Shape shape, Map transitions) { if (!drawn.add(shape)) { - return null; + return this; } String prefix = "s"; diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/IGVShapeVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/IGVShapeVisitor.java Wed Nov 11 15:59:56 2015 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.object.debug; + +import java.util.Map; +import java.util.Map.Entry; + +import com.oracle.truffle.api.nodes.GraphPrintVisitor; +import com.oracle.truffle.api.nodes.GraphPrintVisitor.GraphPrintAdapter; +import com.oracle.truffle.api.nodes.GraphPrintVisitor.GraphPrintHandler; +import com.oracle.truffle.api.object.Shape; +import com.oracle.truffle.object.DebugShapeVisitor; +import com.oracle.truffle.object.ShapeImpl; +import com.oracle.truffle.object.Transition; + +public class IGVShapeVisitor extends DebugShapeVisitor { + private final GraphPrintVisitor graphPrinter; + + public IGVShapeVisitor(GraphPrintVisitor printer) { + this.graphPrinter = printer; + } + + @Override + public IGVShapeVisitor visitShape(final Shape shape, final Map transitions) { + graphPrinter.visit(shape, new GraphPrintHandler() { + public void visit(Object node, GraphPrintAdapter printer) { + if (!printer.visited(node)) { + Shape s = (Shape) node; + printer.createElementForNode(s); + String name = s.getLastProperty() == null ? "ROOT" : s.getLastProperty().toString(); + printer.setNodeProperty(s, "name", name); + printer.setNodeProperty(s, "valid", s.isValid()); + printer.setNodeProperty(s, "identityHashCode", Integer.toHexString(System.identityHashCode(s))); + printer.setNodeProperty(s, "objectType", s.getObjectType()); + + for (Entry entry : transitions.entrySet()) { + Shape dst = entry.getValue(); + ((ShapeImpl) dst).accept(IGVShapeVisitor.this); + assert printer.visited(dst); + printer.connectNodes(s, dst, entry.getKey().getShortName()); + } + } + } + }); + + return this; + } +} diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -50,17 +50,18 @@ import com.oracle.truffle.api.vm.EventConsumer; import com.oracle.truffle.api.vm.PolyglotEngine; import java.io.ByteArrayOutputStream; +import java.util.LinkedList; import java.util.concurrent.Callable; -import java.util.concurrent.Executors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import org.junit.Test; public class SLDebugTest { private Source factorial; private Debugger debugger; - private Callable run; + private final LinkedList> run = new LinkedList<>(); private SuspendedEvent suspendedEvent; private Throwable ex; private ExecutionEvent executionEvent; @@ -89,7 +90,7 @@ ByteArrayOutputStream os = new ByteArrayOutputStream(); - PolyglotEngine engine = PolyglotEngine.buildNew().executor(Executors.newSingleThreadExecutor()).onEvent(new EventConsumer(ExecutionEvent.class) { + PolyglotEngine engine = PolyglotEngine.newBuilder().onEvent(new EventConsumer(ExecutionEvent.class) { @Override protected void on(ExecutionEvent event) { onExecution(event); @@ -101,14 +102,7 @@ } }).setOut(os).build(); - PolyglotEngine.Value value; - synchronized (this) { - value = engine.eval(factorial); - wait(); - } - assertNotNull("Debugger initalized", debugger); - - run(new Callable() { + onEvent(new Callable() { @Override public Void call() throws Exception { LineLocation nMinusOne = factorial.createLineLocation(7); @@ -118,10 +112,11 @@ } }); + PolyglotEngine.Value value = engine.eval(factorial); + assertNull("Parsing done", value.get()); - PolyglotEngine.Value main = engine.findGlobalSymbol("main"); - value = main.invoke(null); + assertExecutedOK(); run(new Callable() { @Override @@ -172,67 +167,62 @@ } }); - run(null); + PolyglotEngine.Value main = engine.findGlobalSymbol("main"); + value = main.invoke(null); + + assertExecutedOK(); Number n = value.as(Number.class); assertNotNull(n); assertEquals("Factorial computed OK", 2, n.intValue()); } - synchronized void onExecution(ExecutionEvent event) { + void onExecution(ExecutionEvent event) { executionEvent = event; debugger = event.getDebugger(); - notifyAll(); - waitForWork(); + performWork(); } - synchronized void onSuspended(SuspendedEvent event) { + void onSuspended(SuspendedEvent event) { suspendedEvent = event; - notifyAll(); - waitForWork(); + performWork(); } - private synchronized void run(Callable callable) throws Throwable { + private void run(Callable callable) throws Throwable { if (ex != null) { throw ex; } - while (run != null) { - wait(); + if (callable == null) { + assertTrue("Assuming all requests processed: " + run, run.isEmpty()); + return; } - run = callable; - notifyAll(); + run.addLast(callable); if (ex != null) { throw ex; } } - private void waitForWork() { + private void performWork() { + Callable c = run.removeFirst(); try { - waitForWork0().call(); - } catch (Throwable tmpEx) { - this.ex = tmpEx; + c.call(); + } catch (Exception e) { + this.ex = e; } - } - private synchronized Callable waitForWork0() { - while (run == null) { - try { - wait(); - } catch (InterruptedException tmpEx) { - throw new IllegalStateException(tmpEx); - } - } - Callable c = run; - run = null; - notifyAll(); - return c; + private void assertExecutedOK() throws Throwable { + run(null); } - void assertLine(int line) { + private void assertLine(int line) { assertNotNull(suspendedEvent); final SourceSection expLoc = factorial.createSection("Line " + line, line); final SourceSection sourceLoc = suspendedEvent.getNode().getEncapsulatingSourceSection(); assertEquals("Exp\n" + expLoc + "\nbut was\n" + sourceLoc, line, sourceLoc.getLineLocation().getLineNumber()); } + + private void onEvent(Callable callable) throws Throwable { + run(callable); + } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLJavaInteropTest.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLJavaInteropTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLJavaInteropTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -74,7 +74,7 @@ String scriptText = "function main() {\n" + " println(\"Called!\");\n" + "}\n"; Source script = Source.fromText(scriptText, "Test").withMimeType("application/x-sl"); ByteArrayOutputStream os = new ByteArrayOutputStream(); - PolyglotEngine engine = PolyglotEngine.buildNew().setOut(os).build(); + PolyglotEngine engine = PolyglotEngine.newBuilder().setOut(os).build(); engine.eval(script); PolyglotEngine.Value main = engine.findGlobalSymbol("main"); final Object value = main.get(); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -69,13 +69,13 @@ @Test public void testVerifyPresence() { - PolyglotEngine vm = PolyglotEngine.buildNew().build(); + PolyglotEngine vm = PolyglotEngine.newBuilder().build(); assertTrue("Our language is present", vm.getLanguages().containsKey("application/x-sl")); } @Override protected PolyglotEngine prepareVM() throws Exception { - PolyglotEngine vm = PolyglotEngine.buildNew().build(); + PolyglotEngine vm = PolyglotEngine.newBuilder().build(); // @formatter:off vm.eval( Source.fromText( diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java Wed Nov 11 15:59:56 2015 -0800 @@ -286,7 +286,7 @@ ByteArrayOutputStream out = new ByteArrayOutputStream(); try { - PolyglotEngine vm = PolyglotEngine.buildNew().setIn(new ByteArrayInputStream(repeat(testCase.testInput, repeats).getBytes("UTF-8"))).setOut(out).build(); + PolyglotEngine vm = PolyglotEngine.newBuilder().setIn(new ByteArrayInputStream(repeat(testCase.testInput, repeats).getBytes("UTF-8"))).setOut(out).build(); String script = readAllLines(testCase.path); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ToStringOfEvalTest.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ToStringOfEvalTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ToStringOfEvalTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -52,7 +52,7 @@ @Test public void checkToStringOnAFunction() throws IOException { - PolyglotEngine engine = PolyglotEngine.buildNew().build(); + PolyglotEngine engine = PolyglotEngine.newBuilder().build(); PolyglotEngine.Language sl = engine.getLanguages().get("application/x-sl"); sl.eval(Source.fromText("function checkName() {}", "defineFn")); PolyglotEngine.Value value1 = engine.findGlobalSymbol("checkName"); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/InstrumentationTestMode.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/InstrumentationTestMode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/InstrumentationTestMode.java Wed Nov 11 15:59:56 2015 -0800 @@ -52,7 +52,7 @@ public static void set(boolean enable) { try { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field instrumenterField = vm.getClass().getDeclaredField("instrumenter"); instrumenterField.setAccessible(true); final Object instrumenter = instrumenterField.get(vm); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Wed Nov 11 15:59:56 2015 -0800 @@ -240,7 +240,7 @@ // We use the name of the file to determine what visitor to attach to it. if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) { // Set up the execution context for Simple and register our two listeners - PolyglotEngine vm = PolyglotEngine.buildNew().setIn(new ByteArrayInputStream(testCase.testInput.getBytes("UTF-8"))).setOut(out).build(); + PolyglotEngine vm = PolyglotEngine.newBuilder().setIn(new ByteArrayInputStream(testCase.testInput.getBytes("UTF-8"))).setOut(out).build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPL.java diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Wed Nov 11 15:59:56 2015 -0800 @@ -50,6 +50,7 @@ import java.util.List; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; @@ -185,7 +186,7 @@ */ /* - * + * *

Tools:
The use of some of Truffle's support for developer tools (based on the * Truffle {@linkplain Instrumenter Instrumentation Framework}) are demonstrated in this file, for * example:

  • a {@linkplain NodeExecCounter counter for node executions}, tabulated by node @@ -226,7 +227,7 @@ * The main entry point. Use the mx command "mx sl" to run it with the correct class path setup. */ public static void main(String[] args) throws IOException { - PolyglotEngine vm = PolyglotEngine.buildNew().build(); + PolyglotEngine vm = PolyglotEngine.newBuilder().build(); assert vm.getLanguages().containsKey("application/x-sl"); setupToolDemos(); @@ -254,21 +255,6 @@ } /** - * Temporary method during API evolution, supports debugger integration. - */ - @Deprecated - public static void run(Source source) throws IOException { - PolyglotEngine vm = PolyglotEngine.buildNew().build(); - assert vm.getLanguages().containsKey("application/x-sl"); - vm.eval(source); - Value main = vm.findGlobalSymbol("main"); - if (main == null) { - throw new SLException("No function main() defined in SL source file."); - } - main.invoke(null); - } - - /** * Parse and run the specified SL source. Factored out in a separate method so that it can also * be used by the unit test harness. */ @@ -434,6 +420,7 @@ failed[0] = e; } return new CallTarget() { + @TruffleBoundary @Override public Object call(Object... arguments) { if (failed[0] instanceof RuntimeException) { diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java Wed Nov 11 15:59:56 2015 -0800 @@ -58,7 +58,7 @@ * generated ones would not be sufficient. */ @TypeSystem({long.class, BigInteger.class, boolean.class, String.class, SLFunction.class, SLNull.class}) -@DSLOptions(useNewLayout = true) +@DSLOptions public abstract class SLTypes { /** diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java Wed Nov 11 15:59:56 2015 -0800 @@ -73,11 +73,10 @@ * We use a separate long specialization to avoid boxing for long. */ @Specialization(limit = "CACHE_LIMIT", guards = {"longLocation != null", "shape.check(receiver)"}, assumptions = "shape.getValidAssumption()") - @SuppressWarnings("unused") protected long doCachedLong(DynamicObject receiver, // @Cached("receiver.getShape()") Shape shape, // @Cached("getLongLocation(shape)") LongLocation longLocation) { - return longLocation.getLong(receiver, true); + return longLocation.getLong(receiver, shape); } protected LongLocation getLongLocation(Shape shape) { @@ -108,27 +107,14 @@ */ @Specialization(contains = "doCachedObject") @TruffleBoundary - protected Object doGeneric(DynamicObject receiver, @Cached("new()") LRUPropertyLookup lruCache) { - if (!lruCache.shape.check(receiver)) { - Shape receiverShape = receiver.getShape(); - lruCache.shape = receiverShape; - lruCache.property = receiverShape.getProperty(propertyName); - } - if (lruCache.property != null) { - return lruCache.property.get(receiver, true); + protected Object doGeneric(DynamicObject receiver) { + Shape shape = receiver.getShape(); + Property property = shape.getProperty(propertyName); + if (property != null) { + return property.get(receiver, shape); } else { return SLNull.SINGLETON; } } - protected static class LRUPropertyLookup { - - private Shape shape; - private Property property; - - public LRUPropertyLookup() { - } - - } - } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java Wed Nov 11 15:59:56 2015 -0800 @@ -42,9 +42,9 @@ import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.InvalidAssumptionException; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.FinalLocationException; @@ -52,8 +52,11 @@ import com.oracle.truffle.api.object.Location; import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; +import com.oracle.truffle.api.utilities.AlwaysValidAssumption; +import com.oracle.truffle.api.utilities.NeverValidAssumption; public abstract class SLWritePropertyCacheNode extends Node { + protected static final int CACHE_LIMIT = 3; protected final String propertyName; @@ -63,105 +66,78 @@ public abstract void executeObject(DynamicObject receiver, Object value); - @Specialization(guards = "location.isValid(receiver, value)", assumptions = "location.getAssumptions()") - public void writeCached(DynamicObject receiver, Object value, // - @Cached("createCachedWrite(receiver, value)") CachedWriteLocation location) { - if (location.writeUnchecked(receiver, value)) { - // write successful - } else { + @Specialization(guards = {"location != null", "shape.check(receiver)", "canSet(location, receiver, value)"}, assumptions = {"shape.getValidAssumption()"}, limit = "CACHE_LIMIT") + public void writeExistingPropertyCached(DynamicObject receiver, Object value, // + @Cached("lookupLocation(receiver, value)") Location location, // + @Cached("receiver.getShape()") Shape shape, // + @Cached("ensureValid(receiver)") Assumption validAssumption) { + try { + validAssumption.check(); + } catch (InvalidAssumptionException e) { executeObject(receiver, value); + return; } - } - - @Specialization(contains = "writeCached") - @TruffleBoundary - public void writeGeneric(DynamicObject receiver, Object value, // - @Cached("new(createCachedWrite(receiver, value))") LRUCachedWriteLocation lru) { - CachedWriteLocation location = lru.location; - if (!location.isValid(receiver, value) || !location.areAssumptionsValid()) { - location = createCachedWrite(receiver, value); - lru.location = location; - } - if (location.writeUnchecked(receiver, value)) { - // write successful - } else { - executeObject(receiver, value); + try { + location.set(receiver, value, shape); + } catch (IncompatibleLocationException | FinalLocationException e) { + throw new IllegalStateException(e); } } - protected CachedWriteLocation createCachedWrite(DynamicObject receiver, Object value) { - while (receiver.updateShape()) { - // multiple shape updates might be needed. - } - - Shape oldShape = receiver.getShape(); - Shape newShape; - Property property = oldShape.getProperty(propertyName); - - if (property != null && property.getLocation().canSet(receiver, value)) { - newShape = oldShape; - } else { - receiver.define(propertyName, value, 0); - newShape = receiver.getShape(); - property = newShape.getProperty(propertyName); - } - - if (!oldShape.check(receiver)) { - return createCachedWrite(receiver, value); + @Specialization(guards = {"existing == null", "shapeBefore.check(receiver)", "canSet(newLocation, receiver, value)"}, assumptions = {"shapeBefore.getValidAssumption()", + "shapeAfter.getValidAssumption()"}, limit = "CACHE_LIMIT") + public void writeNewPropertyCached(DynamicObject receiver, Object value, // + @Cached("lookupLocation(receiver, value)") @SuppressWarnings("unused") Location existing, // + @Cached("receiver.getShape()") Shape shapeBefore, // + @Cached("defineProperty(receiver, value)") Shape shapeAfter, // + @Cached("getLocation(shapeAfter)") Location newLocation, // + @Cached("ensureValid(receiver)") Assumption validAssumption) { + try { + validAssumption.check(); + } catch (InvalidAssumptionException e) { + executeObject(receiver, value); + return; } - - return new CachedWriteLocation(oldShape, newShape, property.getLocation()); - - } - - protected static final class CachedWriteLocation { - - private final Shape oldShape; - private final Shape newShape; - private final Location location; - private final Assumption validLocation = Truffle.getRuntime().createAssumption(); - - public CachedWriteLocation(Shape oldShape, Shape newShape, Location location) { - this.oldShape = oldShape; - this.newShape = newShape; - this.location = location; - } - - public boolean areAssumptionsValid() { - return validLocation.isValid() && oldShape.getValidAssumption().isValid() && newShape.getValidAssumption().isValid(); - } - - public Assumption[] getAssumptions() { - return new Assumption[]{oldShape.getValidAssumption(), newShape.getValidAssumption(), validLocation}; - } - - public boolean isValid(DynamicObject receiver, Object value) { - return oldShape.check(receiver) && location.canSet(receiver, value); - } - - public boolean writeUnchecked(DynamicObject receiver, Object value) { - try { - if (oldShape == newShape) { - location.set(receiver, value, oldShape); - } else { - location.set(receiver, value, oldShape, newShape); - } - return true; - } catch (IncompatibleLocationException | FinalLocationException e) { - validLocation.invalidate(); - return false; - } + try { + newLocation.set(receiver, value, shapeBefore, shapeAfter); + } catch (IncompatibleLocationException e) { + throw new IllegalStateException(e); } } - protected static final class LRUCachedWriteLocation { + @Specialization(contains = {"writeExistingPropertyCached", "writeNewPropertyCached"}) + @TruffleBoundary + public void writeUncached(DynamicObject receiver, Object value) { + receiver.define(propertyName, value); + } - private CachedWriteLocation location; + protected final Location lookupLocation(DynamicObject object, Object value) { + final Shape oldShape = object.getShape(); + final Property property = oldShape.getProperty(propertyName); + + if (property != null && property.getLocation().canSet(object, value)) { + return property.getLocation(); + } else { + return null; + } + } - public LRUCachedWriteLocation(CachedWriteLocation location) { - this.location = location; - } + protected final Shape defineProperty(DynamicObject receiver, Object value) { + Shape oldShape = receiver.getShape(); + Shape newShape = oldShape.defineProperty(propertyName, value, 0); + return newShape; + } + protected final Location getLocation(Shape newShape) { + return newShape.getProperty(propertyName).getLocation(); + } + + protected static Assumption ensureValid(DynamicObject receiver) { + return receiver.updateShape() ? NeverValidAssumption.INSTANCE : AlwaysValidAssumption.INSTANCE; + } + + protected static boolean canSet(Location location, DynamicObject receiver, Object value) { + return location.canSet(receiver, value); } } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLObjectType.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLObjectType.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLObjectType.java Wed Nov 11 15:59:56 2015 -0800 @@ -60,7 +60,7 @@ } @Override - public ForeignAccess getForeignAccessFactory() { + public ForeignAccess getForeignAccessFactory(DynamicObject obj) { return access; } diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java Wed Nov 11 15:59:56 2015 -0800 @@ -134,7 +134,7 @@ } } }; - engine = PolyglotEngine.buildNew().onEvent(onHalted).onEvent(onExec).build(); + engine = PolyglotEngine.newBuilder().onEvent(onHalted).onEvent(onExec).build(); this.language = engine.getLanguages().get(mimeType); if (language == null) { throw new RuntimeException("Implementation not found for \"" + mimeType + "\""); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java Wed Nov 11 15:59:56 2015 -0800 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tools.debug.shell.server; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.oracle.truffle.api.debug.Breakpoint; +import com.oracle.truffle.api.debug.Debugger; +import com.oracle.truffle.api.debug.SuspendedEvent; +import com.oracle.truffle.api.frame.FrameInstance; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.instrument.Visualizer; +import com.oracle.truffle.api.instrument.impl.DefaultVisualizer; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.api.vm.PolyglotEngine.Language; +import com.oracle.truffle.tools.debug.shell.REPLMessage; + +public abstract class REPLServerContext { + + private final int level; + private final SuspendedEvent event; + + protected REPLServerContext(int level, SuspendedEvent event) { + this.level = level; + this.event = event; + } + + /** + * The nesting depth of this context in the current session. + */ + public int getLevel() { + return level; + } + + /** + * The AST node where execution is halted in this context. + */ + public Node getNodeAtHalt() { + return event.getNode(); + } + + /** + * Evaluates given code snippet in the context of currently suspended execution. + * + * @param code the snippet to evaluate + * @param frame null in case the evaluation should happen in top most frame, + * non-null value + * @return result of the evaluation + * @throws IOException if something goes wrong + */ + // public Object eval(String code, FrameInstance frame) throws IOException { + // return event.eval(code, frame); + // } + + /** + * The frame where execution is halted in this context. + */ + public MaterializedFrame getFrameAtHalt() { + return event.getFrame(); + } + + public abstract Language getLanguage(); + + public Visualizer getVisualizer() { + return new DefaultVisualizer(); + } + + public PolyglotEngine engine() { + throw new IllegalStateException(); + } + + protected abstract Debugger db(); + + /** + * Dispatches a REPL request to the appropriate handler. + */ + public abstract REPLMessage[] receive(REPLMessage request); + + public abstract void registerBreakpoint(Breakpoint breakpoint); + + public abstract Breakpoint findBreakpoint(int id); + + public abstract int getBreakpointID(Breakpoint breakpoint); + + /** + * Provides access to the execution stack. + * + * @return immutable list of stack elements + */ + public List getStack() { + List frames = new ArrayList<>(); + int frameCount = 1; + for (FrameInstance frameInstance : event.getStack()) { + if (frameCount == 1) { + frames.add(new FrameDebugDescription(frameCount, event.getNode(), frameInstance)); + } else { + frames.add(new FrameDebugDescription(frameCount, frameInstance.getCallNode(), frameInstance)); + } + frameCount++; + } + return Collections.unmodifiableList(frames); + } + + void prepareStepOut() { + event.prepareStepOut(); + } + + void prepareStepInto(int repeat) { + event.prepareStepInto(repeat); + } + + void prepareStepOver(int repeat) { + event.prepareStepOver(repeat); + } + + void prepareContinue() { + event.prepareContinue(); + } +} diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java --- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -44,7 +44,7 @@ @Test public void testNoExecution() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); @@ -72,7 +72,7 @@ @Test public void testCountingCoverage() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java --- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -45,7 +45,7 @@ @Test public void testNoExecution() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); @@ -61,7 +61,7 @@ @Test public void testMapping1() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); @@ -92,7 +92,7 @@ @Test public void testMapping2() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java --- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -42,7 +42,7 @@ @Test public void testNoExecution() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); @@ -76,7 +76,7 @@ @Test public void testCounting() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java --- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java Wed Nov 11 15:59:56 2015 -0800 @@ -123,7 +123,7 @@ } private static Instrumenter getInstrumenter() throws NoSuchFieldException, IllegalAccessException { - final PolyglotEngine vm = PolyglotEngine.buildNew().build(); + final PolyglotEngine vm = PolyglotEngine.newBuilder().build(); final Field field = PolyglotEngine.class.getDeclaredField("instrumenter"); field.setAccessible(true); final Instrumenter instrumenter = (Instrumenter) field.get(vm); diff -r ad180d3d4bd7 -r 163fdf64587d truffle/overview.html --- a/truffle/overview.html Tue Nov 10 19:42:37 2015 -0800 +++ b/truffle/overview.html Wed Nov 11 15:59:56 2015 -0800 @@ -57,5 +57,33 @@
  • Papers on Graal
+

Keeping Compatibility

+ +

+The Truffle API values work of its adopters and as such it is developed +with compatibility in mind. Methods and features are not removed and renamed +randomly, without a notice and there is a binary compatibility testing framework +in place to verify that. +

+

+On the other hand the Truffle project is still young and needs a way +to refine and change previously taken decisions. To balance the need between +compatibility and give us a way to remove things from the API we following +these rules: +

+
    +
  • Rather than removing/renaming or changing an API element (class, method, + field), mark it deprecated.
  • +
  • Make sure usage of such element can be replaced by non-deprecated ways
  • +
  • Keep such element working until next release
  • +
  • If possible provide automatic migration using Jackpot's META-INF/upgrade/ files
  • +
  • When new (major) release is out, remove it
  • +
+

+By deprecating parts of API while keeping them functional we are giving +users of the Truffle API time to adjust to required +changes and (under the assumption they pay attention to warnings in the code +base) easily identify and migrate to more modern API alternatives. +