# HG changeset patch
# User Christian Humer
# Date 1362153968 -3600
# Node ID 8fa2eed07f81fa7d970af26223d68d305f5a26c2
# Parent 0b48dc5f37c3fd2b9c1d728dc61deb6e1e9fe890# Parent 748cb57f53cb6dde5b16389e6d7da0ca54a89bdd
Merge.
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinFunctionTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinFunctionTest.java Fri Mar 01 17:06:08 2013 +0100
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ *
+ * 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.codegen.test;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Generated code at {@link BuiltinFunctionTestFactory}.
+ */
+public class BuiltinFunctionTest {
+
+ @TypeSystemReference(SimpleTypes.class)
+ abstract static class ValueNode extends Node {
+
+ abstract int executeInt() throws UnexpectedResultException;
+
+ abstract String executeString() throws UnexpectedResultException;
+
+ abstract Object execute();
+
+ }
+
+ abstract static class FunctionNode extends ValueNode {
+
+ @Children ValueNode[] parameters;
+
+ FunctionNode(ValueNode[] parameters) {
+ this.parameters = adoptChildren(parameters);
+ }
+
+ FunctionNode(FunctionNode prev) {
+ this(prev.parameters);
+ }
+ }
+
+ static int convertInt(Object value) {
+ if (value instanceof Number) {
+ return ((Number) value).intValue();
+ } else if (value instanceof String) {
+ return Integer.parseInt((String) value);
+ }
+ throw new RuntimeException("Invalid datatype");
+ }
+
+ abstract static class MathAbsNode extends FunctionNode {
+
+ MathAbsNode(ValueNode[] children) {
+ super(children);
+ }
+
+ MathAbsNode(MathAbsNode prev) {
+ super(prev);
+ }
+
+ @Specialization
+ int doInt(int value1) {
+ return Math.abs(value1);
+ }
+
+ @Generic
+ int doGeneric(Object value0) {
+ return doInt(convertInt(value0));
+ }
+ }
+
+ abstract static class StringThisNode extends ValueNode {
+
+ @Override
+ final String executeString() {
+ return (String) execute();
+ }
+
+ }
+
+ @ExecuteChildren({"thisNode", "parameters"})
+ abstract static class InstanceFunctionNode extends FunctionNode {
+
+ @Child StringThisNode thisNode;
+
+ InstanceFunctionNode(StringThisNode thisNode, ValueNode[] parameters) {
+ super(parameters);
+ this.thisNode = thisNode;
+ }
+
+ InstanceFunctionNode(InstanceFunctionNode prev) {
+ this(prev.thisNode, prev.parameters);
+ }
+ }
+
+ abstract static class StringSubstrNode extends InstanceFunctionNode {
+
+ StringSubstrNode(StringThisNode thisNode, ValueNode[] parameters) {
+ super(thisNode, parameters);
+ }
+
+ StringSubstrNode(StringSubstrNode prev) {
+ super(prev);
+ }
+
+ @Specialization
+ String doInt(String thisValue, int beginIndex, int endIndex) {
+ return thisValue.substring(beginIndex, endIndex);
+ }
+
+ @Generic
+ String doGeneric(String thisValue, Object beginIndex, Object endIndex) {
+ return thisValue.substring(convertInt(beginIndex), convertInt(endIndex));
+ }
+ }
+
+}
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/SimpleTypes.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/SimpleTypes.java Fri Mar 01 17:06:08 2013 +0100
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ *
+ * 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.codegen.test;
+
+import com.oracle.truffle.api.codegen.*;
+
+@TypeSystem({int.class, String.class})
+class SimpleTypes {
+}
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java Fri Mar 01 17:06:08 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+/**
+ * This package contains basic tests of the Truffle-Source-Code-Generation (short Codegen) API and serves at the same
+ * time as an introduction to the Codegen API for language implementors. Every test gives an example on how to use the construct explained in the class description.
+ *
+ *
+ * This API relies heavily on the concepts described in {@link com.oracle.truffle.api.test}. We assume that the
+ * reader is already familiarized with those concepts.
+ *
+ *
+ *
+ * TODO general description
+ *
+ *
+ *
+ * This introduction to Codegen contains items in the following recommended order:
+ *
+ *
+ * - How would you generate builtin functions? {@link com.oracle.truffle.api.codegen.test.BuiltinFunctionTest}
+ *
+ *
+ *
+ */
+package com.oracle.truffle.api.codegen.test;
+
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Fri Mar 01 17:06:08 2013 +0100
@@ -591,6 +591,14 @@
}
String qualified1 = getQualifiedName(type1);
String qualified2 = getQualifiedName(type2);
+
+ if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) {
+ if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) {
+ return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType());
+ } else {
+ return false;
+ }
+ }
return qualified1.equals(qualified2);
}
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java Fri Mar 01 17:06:08 2013 +0100
@@ -27,7 +27,7 @@
import javax.lang.model.element.*;
import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.*;
import com.oracle.truffle.codegen.processor.template.*;
import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
@@ -56,8 +56,11 @@
protected final MethodSpec createDefaultMethodSpec(String shortCircuitName) {
List defaultParameters = new ArrayList<>();
- ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true);
- defaultParameters.add(frameSpec);
+
+ if (getNode().supportsFrame()) {
+ ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true);
+ defaultParameters.add(frameSpec);
+ }
for (NodeFieldData field : getNode().getFields()) {
if (field.getExecutionKind() == ExecutionKind.IGNORE) {
@@ -65,7 +68,12 @@
}
if (field.getExecutionKind() == ExecutionKind.DEFAULT) {
- defaultParameters.add(createValueParameterSpec(field.getName(), field.getNodeData(), false));
+ ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData(), false);
+ if (field.getKind() == FieldKind.CHILDREN) {
+ spec.setCardinality(Cardinality.MULTIPLE);
+ spec.setIndexed(true);
+ }
+ defaultParameters.add(spec);
} else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
String valueName = field.getName();
if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
diff -r 748cb57f53cb -r 8fa2eed07f81 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 Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Fri Mar 01 17:06:08 2013 +0100
@@ -80,31 +80,17 @@
return name;
}
- private static String valueName(NodeFieldData field) {
- return field.getName() + "Value";
- }
-
private static String valueName(ActualParameter param) {
- NodeData node = (NodeData) param.getMethod().getTemplate();
- NodeFieldData field = node.findField(param.getSpecification().getName());
- if (field != null) {
- return valueName(field);
- } else {
- return param.getSpecification().getName();
- }
+ return param.getName();
}
private static String castValueName(ActualParameter parameter) {
return valueName(parameter) + "Cast";
}
- private static String castValueName(NodeFieldData field) {
- return valueName(field) + "Cast";
- }
-
private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) {
- if (forceFrame) {
- method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame"));
+ if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+ method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
}
for (ActualParameter parameter : specialization.getParameters()) {
ParameterSpec spec = parameter.getSpecification();
@@ -116,8 +102,8 @@
}
private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) {
- if (forceFrame) {
- builder.string("frame");
+ if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+ builder.string("frameValue");
}
for (ActualParameter parameter : specialization.getParameters()) {
ParameterSpec spec = parameter.getSpecification();
@@ -125,7 +111,7 @@
continue;
}
- if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) {
+ if (unexpectedValueName != null && parameter.getName().equals(unexpectedValueName)) {
builder.string("ex.getResult()");
} else {
builder.string(valueName(parameter));
@@ -138,7 +124,7 @@
TypeSystemData typeSystem = node.getTypeSystem();
for (ActualParameter targetParameter : targetSpecialization.getParameters()) {
- ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getSpecification().getName());
+ ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getName());
TypeData targetType = targetParameter.getActualTypeData(typeSystem);
TypeData valueType = null;
@@ -276,13 +262,14 @@
}
private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
- NodeData node = guardedSpecialization.getNode();
-
CodeTreeBuilder builder = new CodeTreeBuilder(parent);
// Implict guards based on method signature
- for (NodeFieldData field : node.getFields()) {
- ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName());
- ActualParameter valueParam = valueSpecialization.findParameter(field.getName());
+ for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
+ NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName());
+ if (field == null) {
+ continue;
+ }
+ ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getName());
CodeTree cast = createCast(parent, field, valueParam, guardedParam);
if (cast == null) {
@@ -295,14 +282,15 @@
}
private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
- NodeData node = guardedSpecialization.getNode();
-
CodeTreeBuilder builder = new CodeTreeBuilder(parent);
// Implict guards based on method signature
String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
- for (NodeFieldData field : node.getFields()) {
- ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName());
- ActualParameter valueParam = valueSpecialization.findParameter(field.getName());
+ for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
+ NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName());
+ if (field == null) {
+ continue;
+ }
+ ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getName());
CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam);
if (implicitGuard == null) {
@@ -339,7 +327,7 @@
}
startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem())));
- builder.string(valueName(field));
+ builder.string(valueName(source));
builder.end().end(); // call
if (field.isShortCircuit()) {
@@ -371,7 +359,7 @@
CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target));
- return createLazyAssignment(parent, castValueName(field), target.getActualType(), condition, value);
+ return createLazyAssignment(parent, castValueName(target), target.getActualType(), condition, value);
}
/**
@@ -981,7 +969,7 @@
CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
if (method.getParameters().size() == 1) {
CodeVariableElement var = CodeVariableElement.clone(method.getParameters().get(0));
- var.setName("frame");
+ var.setName("frameValue");
method.getParameters().set(0, var);
}
method.getModifiers().remove(Modifier.ABSTRACT);
@@ -996,7 +984,7 @@
}
if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) {
- buildSpecializeStateMethod(clazz, specialization);
+ buildSpecializeAndExecute(clazz, specialization);
}
}
@@ -1014,7 +1002,7 @@
CodeTree primaryExecuteCall = null;
CodeTreeBuilder executeBuilder = CodeTreeBuilder.createBuilder();
- buildExecute(executeBuilder, null, execType);
+ buildExecute(executeBuilder, null, null, execType);
primaryExecuteCall = executeBuilder.getRoot();
if (needsTry) {
@@ -1168,17 +1156,16 @@
private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) {
CodeTreeBuilder builder = new CodeTreeBuilder(parent);
- for (NodeFieldData field : specialization.getNode().getFields()) {
- if (field.getExecutionKind() == ExecutionKind.IGNORE) {
+ for (ActualParameter parameter : specialization.getParameters()) {
+ NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName());
+ if (field == null) {
continue;
}
- ActualParameter parameterType = specialization.findParameter(field.getName());
-
- if (parameterType.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) {
- buildGenericValueExecute(builder, specialization, field, null);
+ if (parameter.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) {
+ buildGenericValueExecute(builder, specialization, parameter, field, null);
} else {
- buildSpecializedValueExecute(builder, specialization, field);
+ buildSpecializedValueExecute(builder, specialization, parameter, field);
}
}
return builder.getRoot();
@@ -1194,10 +1181,9 @@
}
}
- private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field, NodeFieldData exceptionSpec) {
- ActualParameter specParameter = specialization.findParameter(field.getName());
+ private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) {
NodeData node = specialization.getNode();
- boolean shortCircuit = startShortCircuit(builder, specialization, field, exceptionSpec);
+ boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam);
builder.startStatement();
if (!shortCircuit) {
@@ -1205,19 +1191,19 @@
builder.string(" ");
}
- builder.string(valueName(specParameter));
+ builder.string(valueName(param));
builder.string(" = ");
- ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), specParameter.getActualTypeData(node.getTypeSystem()));
+ ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), param.getActualTypeData(node.getTypeSystem()));
if (genericExecutableType == null) {
throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + Arrays.toString(field.getNodeData().getExecutableTypes()));
}
- buildExecute(builder, field, genericExecutableType);
+ buildExecute(builder, param, field, genericExecutableType);
builder.end();
endShortCircuit(builder, shortCircuit);
}
- private void buildExecute(CodeTreeBuilder builder, NodeFieldData field, ExecutableTypeData execType) {
+ private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) {
if (field != null) {
Element accessElement = field.getAccessElement();
if (accessElement.getKind() == ElementKind.METHOD) {
@@ -1227,18 +1213,20 @@
} else {
throw new AssertionError();
}
+ if (parameter.getSpecification().isIndexed()) {
+ builder.string("[" + parameter.getIndex() + "]");
+ }
builder.string(".");
}
builder.startCall(execType.getMethodName());
if (execType.getParameters().length == 1) {
- builder.string("frame");
+ builder.string("frameValue");
}
builder.end();
}
- private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field) {
- ActualParameter param = specialization.findParameter(field.getName());
- boolean shortCircuit = startShortCircuit(builder, specialization, field, null);
+ private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field) {
+ boolean shortCircuit = startShortCircuit(builder, specialization, param, null);
if (!shortCircuit) {
builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end();
@@ -1250,24 +1238,26 @@
builder.startTryBlock();
}
- builder.startStatement().string(valueName(field)).string(" = ");
- buildExecute(builder, field, execType);
+ builder.startStatement().string(valueName(param)).string(" = ");
+ buildExecute(builder, param, field, execType);
builder.end();
if (execType.hasUnexpectedValue(getContext())) {
builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+ SpecializationData generic = specialization.getNode().getGenericSpecialization();
boolean execute = false;
- for (NodeFieldData exField : specialization.getNode().getFields()) {
- if (exField.getExecutionKind() == ExecutionKind.IGNORE) {
+ for (ActualParameter exParam : generic.getParameters()) {
+ NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName());
+ if (exField == null) {
continue;
}
if (execute) {
- buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exField, field);
- } else if (exField == field) {
+ buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param);
+ } else if (exParam.getName().equals(param.getName())) {
execute = true;
}
}
- builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification()));
+ builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param));
builder.end(); // catch block
}
@@ -1275,12 +1265,16 @@
builder.newLine();
}
- private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData forField, NodeFieldData exceptionField) {
+ private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) {
+ NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName());
+ if (forField == null) {
+ return false;
+ }
+
if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) {
return false;
}
- ActualParameter parameter = specialization.findParameter(forField.getName());
ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
int shortCircuitIndex = 0;
@@ -1297,13 +1291,13 @@
ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex];
startCallOperationMethod(builder, shortCircuitData);
- addValueParameterNames(builder, shortCircuitData, exceptionField != null ? exceptionField.getName() : null, false);
+ addValueParameterNames(builder, shortCircuitData, exceptionParam != null ? exceptionParam.getName() : null, false);
builder.end().end(); // call operation
builder.end(); // statement
builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType()));
- builder.startIf().string(shortCircuitParam.getSpecification().getName()).end();
+ builder.startIf().string(shortCircuitParam.getName()).end();
builder.startBlock();
return true;
@@ -1315,11 +1309,11 @@
}
}
- private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
+ private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) {
CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
specializeCall.startCall("specializeAndExecute");
specializeCall.string(nodeClassName(nextSpecialization) + ".class");
- addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true);
+ addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getName() : null, true);
specializeCall.end().end();
CodeTreeBuilder builder = new CodeTreeBuilder(parent);
@@ -1329,7 +1323,7 @@
return builder.getRoot();
}
- private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) {
+ private void buildSpecializeAndExecute(CodeTypeElement clazz, SpecializationData specialization) {
NodeData node = specialization.getNode();
TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem());
ExecutableTypeData returnExecutableType = node.findExecutableType(returnType);
diff -r 748cb57f53cb -r 8fa2eed07f81 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 Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Fri Mar 01 17:06:08 2013 +0100
@@ -71,6 +71,15 @@
return !noSpecialization;
}
+ public boolean supportsFrame() {
+ for (ExecutableTypeData execType : executableTypes) {
+ if (execType.findParameter("frameValue") == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public List getNodeChildren() {
List children = new ArrayList<>();
for (NodeData child : getDeclaredChildren()) {
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Fri Mar 01 17:06:08 2013 +0100
@@ -28,7 +28,7 @@
public class NodeFieldData {
public enum FieldKind {
- FIELD, CHILD, CHILDREN
+ CHILD, CHILDREN
}
public enum ExecutionKind {
diff -r 748cb57f53cb -r 8fa2eed07f81 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 Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Fri Mar 01 17:06:08 2013 +0100
@@ -208,6 +208,11 @@
specialization.setNode(nodeData);
}
+ // verify specialization parameter length
+ if (!verifySpecializationParameters(specializations)) {
+ return null;
+ }
+
// verify order is not ambiguous
if (!verifySpecializationOrder(typeSystem, specializations)) {
return null;
@@ -247,6 +252,30 @@
return nodeData;
}
+ private boolean verifySpecializationParameters(List specializations) {
+ boolean valid = true;
+ int args = -1;
+ for (SpecializationData specializationData : specializations) {
+ int specializationArgs = 0;
+ for (ActualParameter param : specializationData.getParameters()) {
+ if (!param.getSpecification().isOptional()) {
+ specializationArgs++;
+ }
+ }
+ if (args != -1 && args != specializationArgs) {
+ valid = false;
+ break;
+ }
+ args = specializationArgs;
+ }
+ if (!valid) {
+ for (SpecializationData specialization : specializations) {
+ context.getLog().error(specialization.getMethod(), specialization.getMarkerAnnotation(), "All specializations must have the same number of arguments.");
+ }
+ }
+ return valid;
+ }
+
private boolean verifyMissingAbstractMethods(NodeData nodeData, List elements) {
if (nodeData.needsFactory()) {
// missing abstract methods only needs to be implemented
@@ -424,10 +453,10 @@
nodeType = getComponentType(var.asType());
kind = FieldKind.CHILDREN;
} else {
- mirror = null;
+ execution = ExecutionKind.IGNORE;
nodeType = null;
- kind = FieldKind.FIELD;
- execution = ExecutionKind.IGNORE;
+ mirror = null;
+ kind = null;
}
NodeData fieldNodeData = null;
@@ -444,13 +473,12 @@
context.getLog().error(errorElement, "No executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType));
return null;
}
+
+ // TODO correct handling of access elements
+ if (var.getModifiers().contains(Modifier.PRIVATE) && Utils.typeEquals(var.getEnclosingElement().asType(), parentNodeData.getTemplateType().asType())) {
+ execution = ExecutionKind.IGNORE;
+ }
}
-
- // TODO correct handling of access elements
- if (var.getModifiers().contains(Modifier.PRIVATE) && Utils.typeEquals(var.getEnclosingElement().asType(), parentNodeData.getTemplateType().asType())) {
- execution = ExecutionKind.IGNORE;
- }
-
return new NodeFieldData(fieldNodeData, var, findAccessElement(var), mirror, kind, execution);
}
@@ -617,9 +645,9 @@
}
private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
- for (NodeFieldData field : node.getFields()) {
- ActualParameter parameter = method.findParameter(field.getName());
- if (parameter == null) {
+ for (ActualParameter parameter : method.getParameters()) {
+ NodeFieldData field = node.findField(parameter.getSpecification().getName());
+ if (field == null) {
continue;
}
ExecutableTypeData found = null;
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java Fri Mar 01 17:06:08 2013 +0100
@@ -61,8 +61,7 @@
}
for (ActualParameter param : getParameters()) {
- ParameterSpec paramSpec = param.getSpecification();
- ActualParameter specializationParam = specialization.findParameter(paramSpec.getName());
+ ActualParameter specializationParam = specialization.findParameter(param.getName());
if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) {
return false;
}
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Fri Mar 01 17:06:08 2013 +0100
@@ -31,10 +31,27 @@
private final ParameterSpec specification;
private final TypeMirror actualType;
private TemplateMethod method;
+ private final String name;
+ private final int index;
- public ActualParameter(ParameterSpec specification, TypeMirror actualType) {
+ public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index) {
this.specification = specification;
this.actualType = actualType;
+
+ this.index = index;
+ String valueName = specification.getName() + "Value";
+ if (specification.isIndexed()) {
+ valueName = valueName + index;
+ }
+ this.name = valueName;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public String getName() {
+ return name;
}
void setMethod(TemplateMethod method) {
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Fri Mar 01 17:06:08 2013 +0100
@@ -41,4 +41,14 @@
public List getParameters() {
return parameters;
}
+
+ public ParameterSpec findParameterSpec(String name) {
+ for (ParameterSpec spec : parameters) {
+ if (spec.getName().equals(name)) {
+ return spec;
+ }
+ }
+ return null;
+ }
+
}
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Fri Mar 01 17:06:08 2013 +0100
@@ -39,7 +39,8 @@
private final String name;
private final TypeMirror[] allowedTypes;
private final boolean optional;
- private final Cardinality cardinality;
+ private Cardinality cardinality;
+ private boolean indexed;
public ParameterSpec(String name, TypeMirror[] allowedTypes, boolean optional, Cardinality cardinality) {
this.allowedTypes = allowedTypes;
@@ -63,6 +64,18 @@
this(name, nodeTypeMirrors(nodeData), optional, cardinality);
}
+ public boolean isIndexed() {
+ return indexed;
+ }
+
+ public void setIndexed(boolean indexed) {
+ this.indexed = indexed;
+ }
+
+ public void setCardinality(Cardinality cardinality) {
+ this.cardinality = cardinality;
+ }
+
private static TypeMirror[] nodeTypeMirrors(NodeData nodeData) {
Set typeMirrors = new LinkedHashSet<>();
@@ -95,6 +108,7 @@
for (int i = 0; i < allowedTypes.length; i++) {
TypeMirror mirror = allowedTypes[i];
if (Utils.typeEquals(actualType, mirror)) {
+
return true;
}
}
diff -r 748cb57f53cb -r 8fa2eed07f81 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 Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Fri Mar 01 17:06:08 2013 +0100
@@ -70,7 +70,7 @@
public ActualParameter findParameter(String valueName) {
for (ActualParameter param : getParameters()) {
- if (param.getSpecification().getName().equals(valueName)) {
+ if (param.getName().equals(valueName)) {
return param;
}
}
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Fri Mar 01 17:06:08 2013 +0100
@@ -101,7 +101,7 @@
continue;
}
- E parsedMethod = parse(method, mirror);
+ E parsedMethod = parseNew(method, mirror);
if (parsedMethod != null) {
parsedMethods.add(parsedMethod);
} else {
@@ -114,7 +114,7 @@
return parsedMethods;
}
- private E parse(ExecutableElement method, AnnotationMirror annotation) {
+ private E parseNew(ExecutableElement method, AnnotationMirror annotation) {
MethodSpec methodSpecification = createSpecification(method, annotation);
if (methodSpecification == null) {
return null;
@@ -126,7 +126,7 @@
List parameterSpecs = new ArrayList<>();
parameterSpecs.addAll(methodSpecification.getParameters());
- ActualParameter returnTypeMirror = resolveTypeMirror(returnTypeSpec, method.getReturnType(), template);
+ ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0);
if (returnTypeMirror == null) {
if (isEmitErrors()) {
String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true);
@@ -140,88 +140,65 @@
return null;
}
- Iterator extends VariableElement> variableIterator = method.getParameters().iterator();
+ List parameters = parseParameters(method, parameterSpecs);
+ if (parameters == null) {
+ if (isEmitErrors()) {
+ String message = String.format("Method signature mismatch. Expected signature: \n%s",
+ createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+ context.getLog().error(method, annotation, message);
+ }
+ return null;
+ }
+ ActualParameter[] paramMirrors = parameters.toArray(new ActualParameter[parameters.size()]);
+ return create(new TemplateMethod(template, methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
+ }
+
+ private List parseParameters(ExecutableElement method, List parameterSpecs) {
+ Iterator extends VariableElement> parameterIterator = method.getParameters().iterator();
Iterator extends ParameterSpec> specificationIterator = parameterSpecs.iterator();
- List resolvedMirrors = new ArrayList<>();
- VariableElement parameter = null;
- ParameterSpec specification = null;
- while (specificationIterator.hasNext() || specification != null) {
- if (specification == null) {
- specification = specificationIterator.next();
- }
-
- if (parameter == null && variableIterator.hasNext()) {
- parameter = variableIterator.next();
- }
-
- if (parameter == null) {
- if (specification.getCardinality() == Cardinality.MULTIPLE) {
- specification = null;
- continue;
- } else if (!specification.isOptional()) {
- if (isEmitErrors()) {
- // non option type specification found -> argument missing
- String expectedType = createTypeSignature(specification, typeDefs, false);
-
- String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType,
- createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+ VariableElement parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
+ ParameterSpec specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
- context.getLog().error(method, message);
- }
- return null;
- } else {
- // specification is optional -> continue
- specification = null;
+ int specificationIndex = 0;
+ List resolvedParameters = new ArrayList<>();
+ while (parameter != null || specification != null) {
+ if (parameter == null || specification == null) {
+ if (specification != null && (specification.isOptional() || specification.getCardinality() == Cardinality.MULTIPLE)) {
+ specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+ specificationIndex = 0;
continue;
}
- }
-
- ActualParameter resolvedMirror = resolveTypeMirror(specification, parameter.asType(), template);
-
- if (resolvedMirror == null) {
- if (specification.isOptional()) {
- specification = null;
- continue;
- }
-
- if (isEmitErrors()) {
- String expectedReturnType = createTypeSignature(specification, typeDefs, false);
- String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
-
- String message = String.format("The provided argument type \"%s\" does not match expected type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
- createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
-
- context.getLog().error(parameter, message);
- }
return null;
}
- resolvedMirrors.add(resolvedMirror);
- parameter = null; // consume parameter
+ ActualParameter resolvedParameter = matchParameter(specification, parameter.asType(), template, specificationIndex);
+ if (resolvedParameter == null) {
+ // mismatch
+ if (specification.isOptional()) {
+ specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+ specificationIndex = 0;
+ } else {
+ return null;
+ }
+ } else {
+ resolvedParameters.add(resolvedParameter);
- if (specification.getCardinality() != Cardinality.MULTIPLE) {
- specification = null;
+ // match
+ if (specification.getCardinality() == Cardinality.ONE) {
+ parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
+ specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+ specificationIndex = 0;
+ } else if (specification.getCardinality() == Cardinality.MULTIPLE) {
+ parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
+ specificationIndex++;
+ }
}
}
-
- if (variableIterator.hasNext()) {
- parameter = variableIterator.next();
- if (isEmitErrors()) {
- String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
- String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType,
- createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
-
- context.getLog().error(parameter, message);
- }
- return null;
- }
-
- ActualParameter[] paramMirrors = resolvedMirrors.toArray(new ActualParameter[resolvedMirrors.size()]);
- return create(new TemplateMethod(template, methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
+ return resolvedParameters;
}
- private ActualParameter resolveTypeMirror(ParameterSpec specification, TypeMirror mirror, Template typeSystem) {
+ private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index) {
TypeMirror resolvedType = mirror;
if (hasError(resolvedType)) {
resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem);
@@ -230,7 +207,7 @@
if (!specification.matches(resolvedType)) {
return null;
}
- return new ActualParameter(specification, resolvedType);
+ return new ActualParameter(specification, resolvedType, index);
}
protected List createTypeDefinitions(ParameterSpec returnType, List extends ParameterSpec> parameters) {
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Fri Mar 01 17:06:08 2013 +0100
@@ -54,7 +54,7 @@
@Override
public TypeCastData create(TemplateMethod method) {
TypeData targetType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "as");
- ActualParameter parameter = method.findParameter("value");
+ ActualParameter parameter = method.findParameter("valueValue");
return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType);
}
diff -r 748cb57f53cb -r 8fa2eed07f81 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Thu Feb 28 16:41:44 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Fri Mar 01 17:06:08 2013 +0100
@@ -55,7 +55,7 @@
public TypeCheckData create(TemplateMethod method) {
TypeData checkedType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "is");
assert checkedType != null;
- ActualParameter parameter = method.findParameter("value");
+ ActualParameter parameter = method.findParameter("valueValue");
assert parameter != null;
return new TypeCheckData(method, checkedType, parameter.getActualTypeData(getTypeSystem()));
}
diff -r 748cb57f53cb -r 8fa2eed07f81 mx/projects
--- a/mx/projects Thu Feb 28 16:41:44 2013 +0100
+++ b/mx/projects Fri Mar 01 17:06:08 2013 +0100
@@ -360,6 +360,14 @@
project@com.oracle.truffle.api.codegen@checkstyle=com.oracle.graal.graph
project@com.oracle.truffle.api.codegen@javaCompliance=1.7
+# truffle.api.codegen.test
+project@com.oracle.truffle.api.codegen.test@subDir=graal
+project@com.oracle.truffle.api.codegen.test@sourceDirs=src
+project@com.oracle.truffle.api.codegen.test@dependencies=com.oracle.truffle.api.codegen,JUNIT,com.oracle.truffle.api.test
+project@com.oracle.truffle.api.codegen.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.truffle.api.codegen.test@javaCompliance=1.7
+project@com.oracle.truffle.api.codegen.test@annotationProcessors=com.oracle.truffle.codegen.processor
+
# truffle.codegen.processor
project@com.oracle.truffle.codegen.processor@subDir=graal
project@com.oracle.truffle.codegen.processor@sourceDirs=src