# HG changeset patch # User Christian Humer # Date 1366833003 -7200 # Node ID 8e3a1635cc9e7266e9d6a9318b91d98fa3e46f8d # Parent 39f08ef7b5d8a62470bc718423b614b9f13eff6c Implemented @NodeChild(executeWith={...}). diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/AssumptionsTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/AssumptionsTest.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/AssumptionsTest.java Wed Apr 24 21:50:03 2013 +0200 @@ -38,7 +38,7 @@ @Test public void testSingleAssumption() { Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.create(SingleAssumptionNodeFactory.getInstance(), assumption); + TestRootNode root = TestHelper.createRoot(SingleAssumptionNodeFactory.getInstance(), assumption); Assert.assertEquals(42, TestHelper.executeWith(root)); assumption.invalidate(); @@ -63,7 +63,7 @@ public void testMultipleAssumption() { Assumption assumption1 = Truffle.getRuntime().createAssumption(); Assumption assumption2 = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.create(MultipleAssumptionsNodeFactory.getInstance(), assumption1, assumption2); + TestRootNode root = TestHelper.createRoot(MultipleAssumptionsNodeFactory.getInstance(), assumption1, assumption2); Assert.assertEquals(42, TestHelper.executeWith(root)); assumption2.invalidate(); @@ -95,7 +95,7 @@ public void testDerivedAssumption() { Assumption additionalAssumption = Truffle.getRuntime().createAssumption(); Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.create(DerivedAssumptionNodeFactory.getInstance(), assumption, additionalAssumption); + TestRootNode root = TestHelper.createRoot(DerivedAssumptionNodeFactory.getInstance(), assumption, additionalAssumption); Assert.assertEquals(42, TestHelper.executeWith(root)); assumption.invalidate(); @@ -117,7 +117,7 @@ public void testDerivedAssumptionRedeclared() { Assumption additionalAssumption = Truffle.getRuntime().createAssumption(); Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.create(DerivedAssumptionRedeclaredNodeFactory.getInstance(), additionalAssumption, assumption); + TestRootNode root = TestHelper.createRoot(DerivedAssumptionRedeclaredNodeFactory.getInstance(), additionalAssumption, assumption); Assert.assertEquals(42, TestHelper.executeWith(root)); assumption.invalidate(); diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java Wed Apr 24 21:50:03 2013 +0200 @@ -36,7 +36,7 @@ @Test public void testAdd() { - TestRootNode node = create(AddNodeFactory.getInstance()); + TestRootNode node = createRoot(AddNodeFactory.getInstance()); assertEquals(42, executeWith(node, 19, 23)); assertEquals(42d, executeWith(node, 19d, 23d)); assertEquals(42d, executeWith(node, "19", "23")); @@ -45,7 +45,7 @@ @Test(expected = RuntimeException.class) public void testAddUnsupported() { - TestRootNode node = create(AddNodeFactory.getInstance()); + TestRootNode node = createRoot(AddNodeFactory.getInstance()); executeWith(node, new Object(), new Object()); } diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java Wed Apr 24 21:50:03 2013 +0200 @@ -39,7 +39,7 @@ @Test public void testConcat() { - TestRootNode node = create(StrConcatFactory.getInstance(), new Context()); + TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context()); Str str1 = new Str("42"); Str str2 = new Str(" is the number."); assertEquals(str1.concat(str2), executeWith(node, str1, str2)); @@ -47,13 +47,13 @@ @Test(expected = UnsupportedOperationException.class) public void testConcatUnsupported() { - TestRootNode node = create(StrConcatFactory.getInstance(), new Context()); + TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context()); executeWith(node, 42, new Str(" is the number.")); } @Test public void testSubstrSpecialized() { - TestRootNode node = create(StrSubstrFactory.getInstance(), new Context()); + TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); Str str = new Str("test 42"); assertEquals(str.substr(5, 7), executeWith(node, str, 5, 7)); @@ -61,7 +61,7 @@ @Test public void testSubstrGeneric() { - TestRootNode node = create(StrSubstrFactory.getInstance(), new Context()); + TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); Str str = new Str("test 42"); assertEquals(Str.substr(str, "5", "7"), executeWith(node, str, "5", "7")); @@ -69,27 +69,27 @@ @Test(expected = UnsupportedOperationException.class) public void testSubstrUnsupported() { - TestRootNode node = create(StrSubstrFactory.getInstance(), new Context()); + TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); executeWith(node, new Object(), "5", "7"); } @Test public void testLength() { - TestRootNode node = create(StrLengthFactory.getInstance(), new Context()); + TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context()); Str testStr = new Str("test 42"); assertEquals(testStr.length(), executeWith(node, testStr)); } @Test(expected = UnsupportedOperationException.class) public void testLengthUnsupported() { - TestRootNode node = create(StrLengthFactory.getInstance(), new Context()); + TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context()); executeWith(node, new Object()); } @Test public void testAccessContext() { Context context = new Context(); - TestRootNode node = create(StrAccessContextFactory.getInstance(), context); + TestRootNode node = createRoot(StrAccessContextFactory.getInstance(), context); // accessible by node assertSame(context, node.getNode().getContext()); // accessible by execution diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java Wed Apr 24 21:50:03 2013 +0200 @@ -22,48 +22,86 @@ */ package com.oracle.truffle.api.codegen.test; +import org.junit.*; + import com.oracle.truffle.api.*; import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.DoubleEvaluatedNodeFactory; +import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.EvaluatedNodeFactory; +import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluatedNodeFactory; +import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory; +import com.oracle.truffle.api.codegen.test.TypeSystemTest.ArgumentNode; +import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestArguments; import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; public class ExecuteEvaluatedTest { - /* Represents target[element] */ - @NodeChildren({@NodeChild("target"), @NodeChild("element")}) - abstract static class ReadElementNode extends ValueNode { + @Test + public void testSingleEvaluated() { + ArgumentNode arg0 = new ArgumentNode(0); + CallTarget callTarget = TestHelper.createCallTarget(UseEvaluatedNodeFactory.create(arg0, EvaluatedNodeFactory.create(null))); + + Assert.assertEquals(43, callTarget.call(new TestArguments(42))); + Assert.assertEquals(1, arg0.getInvocationCount()); + } + + @NodeChild("exp") + abstract static class EvaluatedNode extends ValueNode { @Specialization - int getInt(Object[] target, int element) { - return (int) target[element]; + int doExecuteWith(int exp) { + return exp + 1; } - public abstract Object executeWith(VirtualFrame frame, Object targetValue); + public abstract Object executeEvaluated(VirtualFrame frame, Object targetValue); + + public abstract int executeIntEvaluated(VirtualFrame frame, Object targetValue) throws UnexpectedResultException; } - /* Represents target[element]() */ - @NodeChildren({@NodeChild("target"), @NodeChild(value = "element", type = ReadElementNode.class, executeWith = "target")}) - abstract static class ElementCallNode extends ValueNode { + @NodeChildren({@NodeChild("exp0"), @NodeChild(value = "exp1", type = EvaluatedNode.class, executeWith = "exp0")}) + abstract static class UseEvaluatedNode extends ValueNode { @Specialization - Object call(Object receiver, Object callTarget) { - return ((CallTarget) callTarget).call(new TestArguments(receiver)); + int call(int exp0, int exp1) { + Assert.assertEquals(exp0 + 1, exp1); + return exp1; } + } + @Test + public void testDoubleEvaluated() { + ArgumentNode arg0 = new ArgumentNode(0); + ArgumentNode arg1 = new ArgumentNode(1); + CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluatedNodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null))); + + Assert.assertEquals(85, callTarget.call(new TestArguments(42, 43))); + Assert.assertEquals(1, arg0.getInvocationCount()); + Assert.assertEquals(1, arg1.getInvocationCount()); } - public static class TestArguments extends Arguments { + @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1")}) + abstract static class DoubleEvaluatedNode extends ValueNode { - private final Object receiver; - - public TestArguments(Object receiver) { - this.receiver = receiver; + @Specialization + int doExecuteWith(int exp0, int exp1) { + return exp0 + exp1; } - public Object getReceiver() { - return receiver; + public abstract Object executeEvaluated(VirtualFrame frame, Object exp0, Object exp1); + + public abstract int executeIntEvaluated(VirtualFrame frame, Object exp0, Object exp1) throws UnexpectedResultException; + } + + @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp0", "exp1"})}) + abstract static class UseDoubleEvaluatedNode extends ValueNode { + + @Specialization + int call(int exp0, int exp1, int exp2) { + Assert.assertEquals(exp0 + exp1, exp2); + return exp2; } - } } diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java Wed Apr 24 21:50:03 2013 +0200 @@ -40,7 +40,7 @@ @Test public void testGuardInvocations() { - TestRootNode root = create(InvocationGuardFactory.getInstance()); + TestRootNode root = createRoot(InvocationGuardFactory.getInstance()); assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1)); assertEquals(1, InvocationGuard.specializedInvocations); @@ -76,7 +76,7 @@ @Test public void testGuardGlobal() { - TestRootNode root = create(GlobalFlagGuardFactory.getInstance()); + TestRootNode root = createRoot(GlobalFlagGuardFactory.getInstance()); assertEquals(42, executeWith(root, NULL)); diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Wed Apr 24 21:50:03 2013 +0200 @@ -42,7 +42,7 @@ return nodes; } - static TestRootNode create(NodeFactory factory, Object... constants) { + static E createNode(NodeFactory factory, Object... constants) { ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size()); List argumentList = new ArrayList<>(); @@ -52,11 +52,23 @@ } else { argumentList.addAll(Arrays.asList(argumentNodes)); } - return new TestRootNode<>(factory.createNode(argumentList.toArray(new Object[argumentList.size()]))); + return factory.createNode(argumentList.toArray(new Object[argumentList.size()])); + } + + static TestRootNode createRoot(NodeFactory factory, Object... constants) { + return new TestRootNode<>(createNode(factory, constants)); + } + + static CallTarget createCallTarget(ValueNode node) { + return createCallTarget(new TestRootNode<>(node)); + } + + static CallTarget createCallTarget(TestRootNode node) { + return Truffle.getRuntime().createCallTarget(node); } static Object executeWith(TestRootNode node, Object... values) { - return Truffle.getRuntime().createCallTarget(node).call(new TestArguments(values)); + return createCallTarget(node).call(new TestArguments(values)); } } diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Wed Apr 24 21:50:03 2013 +0200 @@ -101,14 +101,20 @@ public static class ArgumentNode extends ValueNode { + private int invocationCount; final int index; public ArgumentNode(int index) { this.index = index; } + public int getInvocationCount() { + return invocationCount; + } + @Override public Object execute(VirtualFrame frame) { + invocationCount++; return ((TestArguments) frame.getArguments()).get(index); } diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Wed Apr 24 21:50:03 2013 +0200 @@ -44,8 +44,8 @@ } @Override - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) { - List execTypes = nodeData.findGenericExecutableTypes(getContext()); + protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) { + List execTypes = nodeData.findGenericExecutableTypes(getContext(), evaluatedCount); List types = new ArrayList<>(); for (ExecutableTypeData type : execTypes) { types.add(type.getType().getPrimitiveType()); @@ -57,7 +57,7 @@ @Override protected ParameterSpec createReturnParameterSpec() { - return super.createValueParameterSpec("returnValue", getNode()); + return super.createValueParameterSpec("returnValue", getNode(), 0); } @Override diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java Wed Apr 24 21:50:03 2013 +0200 @@ -22,10 +22,14 @@ */ package com.oracle.truffle.codegen.processor.node; +import java.util.*; + import javax.lang.model.element.*; import javax.lang.model.type.*; +import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.typesystem.*; public class NodeChildData extends MessageContainer { @@ -54,6 +58,9 @@ private final Cardinality cardinality; private final ExecutionKind executionKind; + + private List executeWith = Collections.emptyList(); + private NodeData nodeData; public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, Element accessElement, Cardinality cardinality, ExecutionKind executionKind) { @@ -66,6 +73,34 @@ this.executionKind = executionKind; } + public List getExecuteWith() { + return executeWith; + } + + void setExecuteWith(List executeWith) { + this.executeWith = executeWith; + } + + public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) { + ExecutableTypeData executableType = nodeData.findExecutableType(targetType, getExecuteWith().size()); + if (executableType == null) { + executableType = findAnyGenericExecutableType(context); + } + return executableType; + } + + public List findGenericExecutableTypes(ProcessorContext context) { + return nodeData.findGenericExecutableTypes(context, getExecuteWith().size()); + } + + public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { + return nodeData.findAnyGenericExecutableType(context, getExecuteWith().size()); + } + + public List findExecutableTypes() { + return nodeData.getExecutableTypes(getExecuteWith().size()); + } + @Override public Element getMessageElement() { return sourceElement; diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Wed Apr 24 21:50:03 2013 +0200 @@ -141,7 +141,7 @@ } } - private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { + private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { CodeTreeBuilder builder = parent.create(); boolean castedValues = sourceMethod != targetMethod; @@ -154,43 +154,47 @@ TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); NodeData node = (NodeData) targetMethod.getTemplate(); - boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType()); - if (accessible) { - if (builder.findMethod().getModifiers().contains(STATIC)) { + if (target == null) { + boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType()); + if (accessible) { + if (builder.findMethod().getModifiers().contains(STATIC)) { + if (method.getModifiers().contains(STATIC)) { + builder.type(targetClass.asType()); + } else { + builder.string(THIS_NODE_LOCAL_VAR_NAME); + } + } else { + if (targetMethod instanceof ExecutableTypeData) { + builder.string("this"); + } else { + builder.string("super"); + } + } + } else { if (method.getModifiers().contains(STATIC)) { builder.type(targetClass.asType()); } else { - builder.string(THIS_NODE_LOCAL_VAR_NAME); - } - } else { - if (targetMethod instanceof ExecutableTypeData) { - builder.string("this"); - } else { - builder.string("super"); + ActualParameter parameter = null; + for (ActualParameter searchParameter : targetMethod.getParameters()) { + if (searchParameter.getSpecification().isSignature()) { + parameter = searchParameter; + break; + } + } + ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); + assert parameter != null; + + if (castedValues && sourceParameter != null) { + builder.string(valueName(sourceParameter, parameter)); + } else { + builder.string(valueName(parameter)); + } } } + builder.string("."); } else { - if (method.getModifiers().contains(STATIC)) { - builder.type(targetClass.asType()); - } else { - ActualParameter parameter = null; - for (ActualParameter searchParameter : targetMethod.getParameters()) { - if (searchParameter.getSpecification().isSignature()) { - parameter = searchParameter; - break; - } - } - ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); - assert parameter != null; - - if (castedValues && sourceParameter != null) { - builder.string(valueName(sourceParameter, parameter)); - } else { - builder.string(valueName(parameter)); - } - } + builder.tree(target); } - builder.string("."); builder.startCall(method.getSimpleName().toString()); for (ActualParameter targetParameter : targetMethod.getParameters()) { @@ -370,7 +374,7 @@ // Explicitly specified guards for (GuardData guard : guardedSpecialization.getGuards()) { builder.string(andOperator); - builder.tree(createTemplateMethodCall(parent, valueSpecialization, guard, null)); + builder.tree(createTemplateMethodCall(parent, null, valueSpecialization, guard, null)); andOperator = " && "; } } @@ -1273,7 +1277,7 @@ emitEncounteredSynthetic(builder); } else { builder.startReturn(); - builder.tree(createTemplateMethodCall(builder, specialization.getNode().getGenericSpecialization(), specialization, null)); + builder.tree(createTemplateMethodCall(builder, null, specialization.getNode().getGenericSpecialization(), specialization, null)); builder.end(); // return } @@ -1429,7 +1433,7 @@ CodeTreeBuilder builder = new CodeTreeBuilder(parent); NodeData node = specialization.getNode(); - ExecutableTypeData castedType = node.findExecutableType(type); + ExecutableTypeData castedType = node.findExecutableType(type, 0); TypeData primaryType = castExecutable.getType(); boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); @@ -1450,7 +1454,7 @@ builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true)); - CodeTree primaryExecuteCall = createTemplateMethodCall(builder, executable, castExecutable, null); + CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null); if (needsTry) { if (!returnVoid) { builder.declaration(primaryType.getPrimitiveType(), "value"); @@ -1517,6 +1521,24 @@ return builder.getRoot(); } + private CodeTree createExpectType(NodeData node, TypeData castedType, CodeTree value) { + if (castedType == null) { + return value; + } else if (castedType.isVoid()) { + return value; + } else if (castedType.isGeneric()) { + return value; + } + + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + String targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(castedType); + startCallTypeSystemMethod(getContext(), builder, node, targetMethodName); + + builder.tree(value); + builder.end().end(); + return builder.getRoot(); + } + private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (specialization.isUninitialized()) { @@ -1606,7 +1628,7 @@ addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); returnBuilder.end(); } else { - returnBuilder.tree(createTemplateMethodCall(returnBuilder, specialization, specialization, null)); + returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); } if (!returnBuilder.isEmpty()) { @@ -1654,7 +1676,7 @@ } TypeData targetType = targetParameter.getTypeSystemType(); - ExecutableTypeData targetExecutable = field.getNodeData().findExecutableType(targetType); + ExecutableTypeData targetExecutable = field.findExecutableType(getContext(), targetType); ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); @@ -1675,7 +1697,7 @@ executionExpression = createExpectType(sourceNode, targetExecutable, CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter))); } } else if (sourceParameter == null) { - executionExpression = createExecuteChildExpression(builder, field, targetParameter); + executionExpression = createExecuteChildExpression(builder, field, targetParameter, unexpectedParameter); } if (executionExpression != null) { @@ -1694,7 +1716,7 @@ private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { for (TemplateMethod listener : node.getSpecializationListeners()) { builder.startStatement(); - builder.tree(createTemplateMethodCall(builder, listener, listener, null)); + builder.tree(createTemplateMethodCall(builder, null, listener, listener, null)); builder.end(); // statement } } @@ -1703,6 +1725,12 @@ ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); boolean unexpected = targetExecutable.hasUnexpectedValue(getContext()); + boolean cast = false; + if (targetExecutable.getType().needsCastTo(param.getTypeSystemType())) { + unexpected = true; + cast = true; + } + builder.startStatement(); if (!shortCircuit) { @@ -1721,7 +1749,11 @@ builder.string(targetVariableName); } builder.string(" = "); - builder.tree(body); + if (cast) { + builder.tree(createExpectType(specialization.getNode(), specialization.getReturnSignature(), body)); + } else { + builder.tree(body); + } builder.end(); if (unexpected) { @@ -1738,9 +1770,9 @@ return builder.getRoot(); } - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter) { + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) { TypeData type = sourceParameter.getTypeSystemType(); - ExecutableTypeData execType = targetField.getNodeData().findExecutableType(type); + ExecutableTypeData execType = targetField.findExecutableType(getContext(), type); /* * FIXME Temporary deactivated due to partial evaluation failure else if @@ -1762,11 +1794,42 @@ } builder.string("."); } + builder.startCall(execType.getMethodName()); - if (execType.getParameters().size() == 1) { - builder.string("frameValue"); + + List signatureParameters = getModel().getSignatureParameters(); + int index = 0; + for (ActualParameter parameter : execType.getParameters()) { + + if (!parameter.getSpecification().isSignature()) { + builder.string(parameter.getLocalName()); + } else { + if (index < signatureParameters.size()) { + ActualParameter specializationParam = signatureParameters.get(index); + + String localName = specializationParam.getLocalName(); + if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) { + localName = "ex.getResult()"; + } + + TypeData sourceType = specializationParam.getTypeSystemType(); + TypeData targetType = parameter.getTypeSystemType(); + + CodeTree value = CodeTreeBuilder.singleString(localName); + + if (sourceType.needsCastTo(targetType)) { + value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value); + } + builder.tree(value); + } else { + builder.defaultValue(parameter.getType()); + } + index++; + } } + builder.end(); + return builder.getRoot(); } @@ -1810,7 +1873,7 @@ builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); - builder.tree(createTemplateMethodCall(builder, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); + builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); builder.end(); // statement return builder.getRoot(); diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Wed Apr 24 21:50:03 2013 +0200 @@ -224,8 +224,8 @@ return methods; } - public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type) { - List types = findGenericExecutableTypes(context); + public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type, int evaluatedCount) { + List types = findGenericExecutableTypes(context, evaluatedCount); for (ExecutableTypeData availableType : types) { if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) { return availableType; @@ -234,8 +234,8 @@ return null; } - public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { - List types = findGenericExecutableTypes(context); + public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) { + List types = findGenericExecutableTypes(context, evaluatedCount); for (ExecutableTypeData type : types) { if (type.getType().isGeneric()) { return type; @@ -261,13 +261,17 @@ } return typeData; } else { - return executableTypes.get(evaluatedCount); + List types = executableTypes.get(evaluatedCount); + if (types == null) { + return Collections.emptyList(); + } + return types; } } - public List findGenericExecutableTypes(ProcessorContext context) { + public List findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) { List types = new ArrayList<>(); - for (ExecutableTypeData type : getExecutableTypes(0)) { + for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { if (!type.hasUnexpectedValue(context)) { types.add(type); } @@ -275,8 +279,8 @@ return types; } - public ExecutableTypeData findExecutableType(TypeData prmitiveType) { - for (ExecutableTypeData type : getExecutableTypes(0)) { + public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) { + for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) { return type; } diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Wed Apr 24 21:50:03 2013 +0200 @@ -42,7 +42,8 @@ return template; } - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) { + @SuppressWarnings("unused") + protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) { ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData)); spec.setSignature(true); return spec; @@ -61,7 +62,7 @@ } protected ParameterSpec createReturnParameterSpec() { - return createValueParameterSpec("returnValue", getNode()); + return createValueParameterSpec("returnValue", getNode(), 0); } @Override @@ -95,7 +96,7 @@ if (getNode().getChildren() != null) { for (NodeChildData child : getNode().getChildren()) { if (child.getExecutionKind() == ExecutionKind.DEFAULT) { - ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData()); + ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size()); if (child.getCardinality().isMany()) { spec.setCardinality(Cardinality.MANY); spec.setIndexed(true); @@ -110,7 +111,7 @@ if (shortCircuitsEnabled) { methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); } - methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData())); + methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData(), child.getExecuteWith().size())); } else { assert false; } diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Wed Apr 24 21:50:03 2013 +0200 @@ -310,7 +310,7 @@ GenericParser parser = new GenericParser(context, node); MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); - ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context); + ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context, 0); assert anyGenericReturnType != null; ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType(), 0, false); @@ -322,7 +322,7 @@ if (child == null) { actualType = specializationParameter.getTypeSystemType(); } else { - ExecutableTypeData paramType = child.getNodeData().findAnyGenericExecutableType(context); + ExecutableTypeData paramType = child.findAnyGenericExecutableType(context); assert paramType != null; actualType = paramType.getType(); } @@ -584,7 +584,7 @@ nodeData.setFields(parseFields(elements)); parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); // parseChildren invokes cyclic parsing. - nodeData.setChildren(parseChildren(templateType, elements, lookupTypes)); + nodeData.setChildren(parseChildren(elements, lookupTypes)); nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); return nodeData; @@ -722,7 +722,7 @@ return fields; } - private List parseChildren(TypeElement templateType, List elements, final List typeHierarchy) { + private List parseChildren(List elements, final List typeHierarchy) { Set shortCircuits = new HashSet<>(); for (ExecutableElement method : ElementFilter.methodsIn(elements)) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); @@ -765,7 +765,7 @@ kind = ExecutionKind.SHORT_CIRCUIT; } - NodeChildData nodeChild = new NodeChildData(templateType, childMirror, name, childType, getter, cardinality, kind); + NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, getter, cardinality, kind); parsedChildren.add(nodeChild); @@ -778,8 +778,6 @@ nodeChild.setNode(fieldNodeData); if (fieldNodeData == null) { nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType)); - } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) { - nodeChild.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(type)); } } } @@ -793,6 +791,53 @@ encounteredNames.add(child.getName()); } } + + for (NodeChildData child : filteredChildren) { + List executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); + AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); + List executeWith = new ArrayList<>(); + for (String executeWithString : executeWithStrings) { + + if (child.getName().equals(executeWithString)) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString); + continue; + } + + NodeChildData found = null; + boolean before = true; + for (NodeChildData resolveChild : filteredChildren) { + if (resolveChild == child) { + before = false; + continue; + } + if (resolveChild.getName().equals(executeWithString)) { + found = resolveChild; + break; + } + } + + if (found == null) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString); + continue; + } else if (!before) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString, + executeWithString); + continue; + } + executeWith.add(found); + } + child.setExecuteWith(executeWith); + if (child.getNodeData() == null) { + continue; + } + + List types = child.findGenericExecutableTypes(context); + if (types.isEmpty()) { + child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType())); + continue; + } + } + return filteredChildren; } @@ -930,7 +975,7 @@ continue; } ExecutableTypeData found = null; - List executableElements = field.getNodeData().findGenericExecutableTypes(context); + List executableElements = field.findGenericExecutableTypes(context); for (ExecutableTypeData executable : executableElements) { if (executable.getType().equalsType(parameter.getTypeSystemType())) { found = executable; diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Wed Apr 24 21:50:03 2013 +0200 @@ -85,11 +85,11 @@ return true; } for (ActualParameter parameter : getParameters()) { - NodeChildData field = getNode().findChild(parameter.getSpecification().getName()); - if (field == null) { + NodeChildData child = getNode().findChild(parameter.getSpecification().getName()); + if (child == null) { continue; } - ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getTypeSystemType()); + ExecutableTypeData type = child.findExecutableType(context, parameter.getTypeSystemType()); if (type.hasUnexpectedValue(context)) { return true; } diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java Wed Apr 24 21:50:03 2013 +0200 @@ -34,11 +34,15 @@ private final List messages = new ArrayList<>(); public final void addWarning(String text, Object... params) { - getMessages().add(new Message(this, String.format(text, params), Kind.WARNING)); + getMessages().add(new Message(null, this, String.format(text, params), Kind.WARNING)); } public final void addError(String text, Object... params) { - getMessages().add(new Message(this, String.format(text, params), Kind.ERROR)); + addError(null, text, params); + } + + public final void addError(AnnotationValue value, String text, Object... params) { + getMessages().add(new Message(value, this, String.format(text, params), Kind.ERROR)); } protected List findChildContainers() { @@ -150,15 +154,21 @@ public static final class Message { private final MessageContainer originalContainer; + private final AnnotationValue annotationValue; private final String text; private final Kind kind; - public Message(MessageContainer originalContainer, String text, Kind kind) { + public Message(AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) { + this.annotationValue = annotationValue; this.originalContainer = originalContainer; this.text = text; this.kind = kind; } + public AnnotationValue getAnnotationValue() { + return annotationValue; + } + public MessageContainer getOriginalContainer() { return originalContainer; } diff -r 39f08ef7b5d8 -r 8e3a1635cc9e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Wed Apr 24 18:39:41 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Wed Apr 24 21:50:03 2013 +0200 @@ -206,6 +206,17 @@ return types; } + public List getSignatureParameters() { + List types = new ArrayList<>(); + for (ActualParameter parameter : getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + types.add(parameter); + } + return types; + } + @Override public int compareTo(TemplateMethod o) { if (this == o) {