# HG changeset patch # User Christian Humer # Date 1391516356 -3600 # Node ID b77c097864451bdedec8ec25130573cd5020b1b1 # Parent 5365f8d35b06b67b345769bb3224a030fc32573c# Parent 82090a107bae85bb690b9ef74a694a5f69e1922c Merge. diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java Tue Feb 04 13:19:16 2014 +0100 @@ -22,18 +22,22 @@ */ package com.oracle.truffle.api.dsl.test; +import java.util.*; + import org.junit.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; -import com.oracle.truffle.api.dsl.test.UnsupportedSpecializationTestFactory.Undefined1Factory; +import com.oracle.truffle.api.dsl.test.UnsupportedSpecializationTestFactory.Unsupported1Factory; +import com.oracle.truffle.api.dsl.test.UnsupportedSpecializationTestFactory.Unsupported2Factory; +import com.oracle.truffle.api.nodes.*; public class UnsupportedSpecializationTest { @Test - public void testUndefined1() { - TestRootNode root = TestHelper.createRoot(Undefined1Factory.getInstance()); + public void testUnsupported1() { + TestRootNode root = TestHelper.createRoot(Unsupported1Factory.getInstance()); try { TestHelper.executeWith(root, ""); Assert.fail(); @@ -41,12 +45,13 @@ Assert.assertNotNull(e.getSuppliedValues()); Assert.assertEquals(1, e.getSuppliedValues().length); Assert.assertEquals("", e.getSuppliedValues()[0]); + Assert.assertSame(root.getNode().getChildren().iterator().next(), e.getSuppliedNodes()[0]); Assert.assertEquals(root.getNode(), e.getNode()); } } @NodeChild("a") - abstract static class Undefined1 extends ValueNode { + abstract static class Unsupported1 extends ValueNode { @Specialization public int doInteger(@SuppressWarnings("unused") int a) { @@ -54,5 +59,41 @@ } } - // TODO more tests required + @Test + public void testUnsupported2() { + TestRootNode root = TestHelper.createRoot(Unsupported2Factory.getInstance()); + try { + TestHelper.executeWith(root, "", 1); + Assert.fail(); + } catch (UnsupportedSpecializationException e) { + Assert.assertNotNull(e.getSuppliedValues()); + Assert.assertNotNull(e.getSuppliedNodes()); + Assert.assertEquals(3, e.getSuppliedValues().length); + Assert.assertEquals(3, e.getSuppliedNodes().length); + Assert.assertEquals("", e.getSuppliedValues()[0]); + Assert.assertEquals(false, e.getSuppliedValues()[1]); + Assert.assertEquals(null, e.getSuppliedValues()[2]); + List children = NodeUtil.findNodeChildren(root.getNode()); + Assert.assertSame(children.get(0), e.getSuppliedNodes()[0]); + Assert.assertNull(e.getSuppliedNodes()[1]); + Assert.assertSame(children.get(1), e.getSuppliedNodes()[2]); + Assert.assertEquals(root.getNode(), e.getNode()); + } + } + + @SuppressWarnings("unused") + @NodeChildren({@NodeChild("a"), @NodeChild("b")}) + abstract static class Unsupported2 extends ValueNode { + + @ShortCircuit("b") + public boolean needsB(Object a) { + return false; + } + + @Specialization + public int doInteger(int a, boolean hasB, int b) { + throw new AssertionError(); + } + } + } diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java Tue Feb 04 13:19:16 2014 +0100 @@ -37,11 +37,17 @@ private static final long serialVersionUID = -2122892028296836269L; private final Node node; + private final Node[] suppliedNodes; private final Object[] suppliedValues; - public UnsupportedSpecializationException(Node node, Object... suppliedValues) { + public UnsupportedSpecializationException(Node node, Node[] suppliedNodes, Object... suppliedValues) { super("Unexpected values provided for " + node + ": " + Arrays.toString(suppliedValues)); + Objects.requireNonNull(suppliedNodes, "The suppliedNodes parameter must not be null."); + if (suppliedNodes.length != suppliedValues.length) { + throw new IllegalArgumentException("The length of suppliedNodes must match the length of suppliedValues."); + } this.node = node; + this.suppliedNodes = suppliedNodes; this.suppliedValues = suppliedValues; } @@ -53,7 +59,19 @@ } /** - * Returns the dynamic values that were supplied to the node. + * Returns the children of the {@link Node} returned by {@link #getNode()} which produced the + * values returned by {@link #getSuppliedValues()}. The array returned by + * {@link #getSuppliedNodes()} has the same length as the array returned by + * {@link #getSuppliedValues()}. Never returns null. + */ + public Node[] getSuppliedNodes() { + return suppliedNodes; + } + + /** + * Returns the dynamic values that were supplied to the node.The array returned by + * {@link #getSuppliedNodes()} has the same length as the array returned by + * {@link #getSuppliedValues()}. Never returns null. */ public Object[] getSuppliedValues() { return suppliedValues; diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Tue Feb 04 13:19:16 2014 +0100 @@ -343,6 +343,12 @@ LinkedHashMap nodes = new LinkedHashMap<>(); NodeClass nodeClass = NodeClass.get(node.getClass()); + if (node instanceof CallNode) { + RootNode inlinedRoot = ((CallNode) node).getInlinedRoot(); + if (inlinedRoot != null) { + nodes.put("inlinedRoot", inlinedRoot); + } + } for (NodeField field : nodeClass.getFields()) { NodeFieldKind kind = field.getKind(); if (kind == NodeFieldKind.CHILD || kind == NodeFieldKind.CHILDREN) { diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Tue Feb 04 13:19:16 2014 +0100 @@ -43,8 +43,8 @@ public static final String OPTION_DETAILED_REWRITE_REASONS = "DetailedRewriteReasons"; - private final TypeMirror node; - private final TypeMirror nodeArray; + private final DeclaredType node; + private final ArrayType nodeArray; private final TypeMirror unexpectedValueException; private final TypeMirror frame; private final TypeMirror assumption; @@ -131,11 +131,11 @@ return compilerDirectives; } - public TypeMirror getNode() { + public DeclaredType getNode() { return node; } - public TypeMirror getNodeArray() { + public ArrayType getNodeArray() { return nodeArray; } diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Feb 04 13:19:16 2014 +0100 @@ -99,6 +99,22 @@ return param.getLocalName(); } + private static CodeTree createAccessChild(NodeExecutionData targetExecution) { + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + Element accessElement = targetExecution.getChild().getAccessElement(); + if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { + builder.string("this.").string(targetExecution.getChild().getName()); + } else if (accessElement.getKind() == ElementKind.FIELD) { + builder.string("this.").string(accessElement.getSimpleName().toString()); + } else { + throw new AssertionError(); + } + if (targetExecution.isIndexed()) { + builder.string("[" + targetExecution.getIndex() + "]"); + } + return builder.getRoot(); + } + private static String castValueName(ActualParameter parameter) { return valueName(parameter) + "Cast"; } @@ -155,18 +171,14 @@ } private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { - if (sourceParameter != null) { - if (!sourceParameter.getSpecification().isSignature()) { - return valueName(targetParameter); - } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { - if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) { - return castValueName(targetParameter); - } + if (!sourceParameter.getSpecification().isSignature()) { + return valueName(targetParameter); + } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { + if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) { + return castValueName(targetParameter); } - return valueName(targetParameter); - } else { - return valueName(targetParameter); } + return valueName(targetParameter); } private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, @@ -331,9 +343,35 @@ } protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) { + CodeTreeBuilder nodes = builder.create(); + CodeTreeBuilder arguments = builder.create(); + nodes.startCommaGroup(); + arguments.startCommaGroup(); + boolean empty = true; + for (ActualParameter parameter : current.getParameters()) { + NodeExecutionData executionData = parameter.getSpecification().getExecution(); + if (executionData != null) { + if (executionData.isShortCircuit()) { + nodes.nullLiteral(); + arguments.string(valueName(parameter.getPreviousParameter())); + } + nodes.tree(createAccessChild(executionData)); + arguments.string(valueName(parameter)); + empty = false; + } + } + nodes.end(); + arguments.end(); + builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class)); builder.string("this"); - addInternalValueParameterNames(builder, current, current, null, false, null); + builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null); + + builder.tree(nodes.getRoot()); + builder.end(); + if (!empty) { + builder.tree(arguments.getRoot()); + } builder.end().end(); } @@ -965,16 +1003,12 @@ for (ActualParameter param : getModel().getSignatureParameters()) { NodeExecutionData execution = param.getSpecification().getExecution(); - CodeTreeBuilder access = builder.create(); - access.string("this.").string(execution.getChild().getName()); - if (execution.isIndexed()) { - access.string("[").string(String.valueOf(execution.getIndex())).string("]"); - } + CodeTree access = createAccessChild(execution); String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName()); oldBuilder.declaration(execution.getChild().getNodeData().getNodeType(), oldName, access); - nullBuilder.startStatement().tree(access.getRoot()).string(" = null").end(); - resetBuilder.startStatement().tree(access.getRoot()).string(" = ").string(oldName).end(); + nullBuilder.startStatement().tree(access).string(" = null").end(); + resetBuilder.startStatement().tree(access).string(" = ").string(oldName).end(); } builder.tree(oldBuilder.getRoot()); @@ -2274,7 +2308,7 @@ private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (targetExecution != null) { - builder.tree(createAccessChild(builder, targetExecution)); + builder.tree(createAccessChild(targetExecution)); builder.string("."); } @@ -2328,22 +2362,6 @@ return builder.getRoot(); } - private CodeTree createAccessChild(CodeTreeBuilder parent, NodeExecutionData targetExecution) throws AssertionError { - CodeTreeBuilder builder = parent.create(); - Element accessElement = targetExecution.getChild().getAccessElement(); - if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { - builder.string("this.").string(targetExecution.getChild().getName()); - } else if (accessElement.getKind() == ElementKind.FIELD) { - builder.string("this.").string(accessElement.getSimpleName().toString()); - } else { - throw new AssertionError(); - } - if (targetExecution.isIndexed()) { - builder.string("[" + targetExecution.getIndex() + "]"); - } - return builder.getRoot(); - } - private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { NodeExecutionData execution = parameter.getSpecification().getExecution(); if (execution == null || !execution.isShortCircuit()) { diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Tue Feb 04 13:19:16 2014 +0100 @@ -154,8 +154,10 @@ /* Change to true if you want to see the AST on the console. */ boolean printASTToLog = false; + /* Change to dump the AST to IGV over the network. */ + boolean dumpASTToIGV = false; - printScript("before execution", context, logOutput, printASTToLog); + printScript("before execution", context, logOutput, printASTToLog, dumpASTToIGV); try { for (int i = 0; i < repeats; i++) { long start = System.nanoTime(); @@ -176,7 +178,7 @@ } } finally { - printScript("after execution", context, logOutput, printASTToLog); + printScript("after execution", context, logOutput, printASTToLog, dumpASTToIGV); } } @@ -184,21 +186,27 @@ * Dumps the AST of all functions to the IGV visualizer, via a socket connection. IGV can be * started with the mx command "mx igv". Optionally, also prints the ASTs to the console. */ - private static void printScript(String groupName, SLContext context, PrintStream logOutput, boolean printASTToLog) { - GraphPrintVisitor graphPrinter = new GraphPrintVisitor(); - graphPrinter.beginGroup(groupName); - for (SLFunction function : context.getFunctionRegistry().getFunctions()) { - RootCallTarget callTarget = function.getCallTarget(); - if (callTarget != null) { - graphPrinter.beginGraph(function.toString()).visit(callTarget.getRootNode()); - - if (logOutput != null && printASTToLog) { + private static void printScript(String groupName, SLContext context, PrintStream logOutput, boolean printASTToLog, boolean dumpASTToIGV) { + if (dumpASTToIGV) { + GraphPrintVisitor graphPrinter = new GraphPrintVisitor(); + graphPrinter.beginGroup(groupName); + for (SLFunction function : context.getFunctionRegistry().getFunctions()) { + RootCallTarget callTarget = function.getCallTarget(); + if (callTarget != null) { + graphPrinter.beginGraph(function.toString()).visit(callTarget.getRootNode()); + } + } + graphPrinter.printToNetwork(true); + } + if (printASTToLog && logOutput != null) { + for (SLFunction function : context.getFunctionRegistry().getFunctions()) { + RootCallTarget callTarget = function.getCallTarget(); + if (callTarget != null) { logOutput.println("=== " + function); NodeUtil.printTree(logOutput, callTarget.getRootNode()); } } } - graphPrinter.printToNetwork(true); } /** @@ -223,8 +231,10 @@ result.append(" not defined for"); String sep = " "; - for (Object value : ex.getSuppliedValues()) { - if (value != null) { + for (int i = 0; i < ex.getSuppliedValues().length; i++) { + Object value = ex.getSuppliedValues()[i]; + Node node = ex.getSuppliedNodes()[i]; + if (node != null) { result.append(sep); sep = ", "; @@ -238,6 +248,9 @@ result.append("Function ").append(value); } else if (value == SLNull.SINGLETON) { result.append("NULL"); + } else if (value == null) { + // value is not evaluated because of short circuit evaluation + result.append("ANY"); } else { result.append(value); } diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLCallNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLCallNode.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLCallNode.java Tue Feb 04 13:19:16 2014 +0100 @@ -79,7 +79,7 @@ * program. We report it with the same exception that Truffle DSL generated nodes use to * report type errors. */ - throw new UnsupportedSpecializationException(this, ex.getResult()); + throw new UnsupportedSpecializationException(this, new Node[]{functionNode}, ex.getResult()); } } } diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Tue Feb 04 13:19:16 2014 +0100 @@ -92,7 +92,7 @@ * program. We report it with the same exception that Truffle DSL generated nodes use to * report type errors. */ - throw new UnsupportedSpecializationException(this, ex.getResult()); + throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult()); } } } diff -r 82090a107bae -r b77c09786445 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Mon Feb 03 17:16:52 2014 -0800 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Tue Feb 04 13:19:16 2014 +0100 @@ -107,7 +107,7 @@ * program. We report it with the same exception that Truffle DSL generated nodes use to * report type errors. */ - throw new UnsupportedSpecializationException(this, ex.getResult()); + throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult()); } } }