# HG changeset patch # User Christian Humer # Date 1391457597 -3600 # Node ID 28479abd1a69c4e6def042f68b802b7bbe0a22bb # Parent 6b91134526a798341c70fcdab97bf6e5dd63821b Truffle-DSL: implemented support for UnsupportedSpecializationException#getSuppliedNodes(). diff -r 6b91134526a7 -r 28479abd1a69 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 15:49:58 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java Mon Feb 03 20:59:57 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 6b91134526a7 -r 28479abd1a69 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 15:49:58 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java Mon Feb 03 20:59:57 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 6b91134526a7 -r 28479abd1a69 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 15:49:58 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Mon Feb 03 20:59:57 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 6b91134526a7 -r 28479abd1a69 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 15:49:58 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Mon Feb 03 20:59:57 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()) {