# HG changeset patch # User Christian Humer # Date 1364845400 -7200 # Node ID 8a1115c92271d4842651b59475fbfaaba7e2fa77 # Parent ce6e8672f798a7ab6fd24f9e06d554282297a662 Implemented codegen guard definitions can now omit unused parameters. diff -r ce6e8672f798 -r 8a1115c92271 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java Mon Apr 01 21:43:20 2013 +0200 @@ -33,7 +33,7 @@ */ public class Log { - public static final boolean DEBUG = false; + public static final boolean DEBUG = true; private final ProcessingEnvironment processingEnv; diff -r ce6e8672f798 -r 8a1115c92271 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Mon Apr 01 21:43:20 2013 +0200 @@ -42,18 +42,16 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + List types = new ArrayList<>(); types.addAll(getNode().getTypeSystem().getPrimitiveTypeMirrors()); types.add(getContext().getType(void.class)); ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types); returnTypeSpec.setSignature(true); - - List parameters = new ArrayList<>(); - ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()); - frameSpec.setOptional(true); - parameters.add(frameSpec); - return new MethodSpec(new ArrayList(), returnTypeSpec, parameters); + MethodSpec spec = new MethodSpec(returnTypeSpec); + spec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); + return spec; } @Override diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Mon Apr 01 21:43:20 2013 +0200 @@ -44,7 +44,7 @@ } @Override - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, boolean optional) { + protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) { List execTypes = nodeData.findGenericExecutableTypes(getContext()); List types = new ArrayList<>(); for (ExecutableTypeData type : execTypes) { @@ -57,7 +57,7 @@ @Override protected ParameterSpec createReturnParameterSpec() { - return super.createValueParameterSpec("returnValue", getNode(), false); + return super.createValueParameterSpec("returnValue", getNode()); } @Override diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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.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.node.NodeFieldData.*; -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; - -public abstract class MethodParser extends TemplateMethodParser { - - public MethodParser(ProcessorContext context, NodeData node) { - super(context, node); - } - - public NodeData getNode() { - return template; - } - - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, boolean optional) { - ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData)); - spec.setOptional(optional); - spec.setSignature(true); - return spec; - } - - private static List nodeTypeMirrors(NodeData nodeData) { - Set typeMirrors = new LinkedHashSet<>(); - - for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { - typeMirrors.add(typeData.getType().getPrimitiveType()); - } - - typeMirrors.add(nodeData.getTypeSystem().getGenericType()); - - return new ArrayList<>(typeMirrors); - } - - protected ParameterSpec createReturnParameterSpec() { - return createValueParameterSpec("operation", getNode(), false); - } - - @Override - public boolean isParsable(ExecutableElement method) { - return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; - } - - @SuppressWarnings("unused") - protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, String shortCircuitName) { - List defaultParameters = new ArrayList<>(); - - if (getNode().supportsFrame()) { - ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()); - frameSpec.setOptional(true); - defaultParameters.add(frameSpec); - } - - TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType(); - - List prefixTypes = new ArrayList<>(); - - if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(declaredType, template.getNodeType())) { - prefixTypes.add(getNode().getTemplateType().asType()); - } - - for (NodeFieldData field : getNode().getFields()) { - if (field.getKind() == FieldKind.FIELD) { - ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); - spec.setOptional(true); - spec.setLocal(true); - defaultParameters.add(spec); - } - } - - for (NodeFieldData field : getNode().getFields()) { - if (field.getExecutionKind() == ExecutionKind.IGNORE) { - continue; - } - - if (field.getExecutionKind() == ExecutionKind.DEFAULT) { - 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)) { - break; - } - - defaultParameters.add(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); - defaultParameters.add(createValueParameterSpec(valueName, field.getNodeData(), false)); - } else { - assert false; - } - } - - return new MethodSpec(prefixTypes, createReturnParameterSpec(), defaultParameters); - } - - private static String shortCircuitValueName(String valueName) { - return "has" + Utils.firstLetterUpperCase(valueName); - } - -} diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Mon Apr 01 21:43:20 2013 +0200 @@ -117,24 +117,28 @@ } } - private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod target, TemplateMethod sourceMethod, TemplateMethod castMethod, String unexpectedValueName) { + private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { CodeTreeBuilder builder = parent.create(); - boolean castedValues = sourceMethod != castMethod; + boolean castedValues = sourceMethod != targetMethod; builder.startGroup(); - ExecutableElement method = target.getMethod(); + ExecutableElement method = targetMethod.getMethod(); if (method == null) { - throw new IllegalStateException("Cannot call synthtetic operation methods."); + throw new IllegalStateException("Cannot call synthetic operation methods."); } TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); - NodeData node = (NodeData) castMethod.getTemplate(); + NodeData node = (NodeData) targetMethod.getTemplate(); TypeSystemData typeSystem = node.getTypeSystem(); - boolean accessible = target.canBeAccessedByInstanceOf(node.getNodeType()); + boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); if (accessible) { if (builder.findMethod().getModifiers().contains(STATIC)) { - builder.string(THIS_NODE_LOCAL_VAR_NAME); + if (method.getModifiers().contains(STATIC)) { + builder.type(targetClass.asType()); + } else { + builder.string(THIS_NODE_LOCAL_VAR_NAME); + } } else { builder.string("super"); } @@ -143,8 +147,8 @@ builder.type(targetClass.asType()); } else { ActualParameter parameter = null; - for (ActualParameter searchParameter : target.getParameters()) { - if (!searchParameter.getSpecification().isOptional()) { + for (ActualParameter searchParameter : targetMethod.getParameters()) { + if (searchParameter.getSpecification().isSignature()) { parameter = searchParameter; break; } @@ -172,10 +176,10 @@ builder.string("."); builder.startCall(method.getSimpleName().toString()); - for (ActualParameter targetParameter : castMethod.getParameters()) { + for (ActualParameter targetParameter : targetMethod.getParameters()) { ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); if (valueParameter == null) { - continue; + valueParameter = targetParameter; } TypeData targetType = targetParameter.getActualTypeData(typeSystem); @@ -257,12 +261,34 @@ body.string(".").startCall(methodName); } - private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization, + private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues, CodeTree guardedStatements, CodeTree elseStatements) { + NodeData node = targetSpecialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); - CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, valueSpecialization, guardedSpecialization); - CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, valueSpecialization, guardedSpecialization); + CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization); + CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization); + + Set valuesNeedsCast; + if (castValues) { + // cast all + valuesNeedsCast = null; + } else { + // find out which values needs a cast + valuesNeedsCast = new HashSet<>(); + for (GuardData guard : targetSpecialization.getGuards()) { + for (ActualParameter parameter : guard.getParameters()) { + NodeFieldData field = node.findField(parameter.getSpecification().getName()); + if (field == null) { + continue; + } + TypeData typeData = parameter.getActualTypeData(node.getTypeSystem()); + if (typeData != null && !typeData.isGeneric()) { + valuesNeedsCast.add(parameter.getLocalName()); + } + } + } + } int ifCount = 0; @@ -274,9 +300,7 @@ ifCount++; } - if (explicitGuards != null || !onSpecialization) { - builder.tree(createCasts(parent, valueSpecialization, guardedSpecialization)); - } + builder.tree(createCasts(parent, valuesNeedsCast, sourceSpecialization, targetSpecialization)); if (explicitGuards != null) { builder.startIf(); @@ -309,7 +333,7 @@ // Explicitly specified guards for (GuardData guard : guardedSpecialization.getGuards()) { builder.string(andOperator); - builder.tree(createTemplateMethodCall(parent, guard, valueSpecialization, guardedSpecialization, null)); + builder.tree(createTemplateMethodCall(parent, valueSpecialization, guard, null)); andOperator = " && "; } } @@ -317,7 +341,7 @@ return builder.isEmpty() ? null : builder.getRoot(); } - private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { + private CodeTree createCasts(CodeTreeBuilder parent, Set castWhiteList, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); // Implict guards based on method signature for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { @@ -327,6 +351,10 @@ } ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); + if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) { + continue; + } + CodeTree cast = createCast(parent, field, valueParam, guardedParam); if (cast == null) { continue; @@ -943,7 +971,7 @@ CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize"); method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); - addInternalValueParameters(method, node.getGenericSpecialization(), false); + addInternalValueParameters(method, node.getGenericSpecialization(), true); CodeTreeBuilder body = method.createBuilder(); body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); @@ -957,7 +985,7 @@ guarded.string(THIS_NODE_LOCAL_VAR_NAME); guarded.end().end(); - body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); + body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, false, guarded.getRoot(), null)); } body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); @@ -1013,7 +1041,7 @@ addInternalValueParameterNames(nextBuilder, next, null, true, true); nextBuilder.end().end(); - invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, nextBuilder.getRoot()); + invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot()); } builder.tree(invokeMethod); @@ -1032,7 +1060,7 @@ emitEncounteredSynthetic(builder); } else { builder.startReturn(); - builder.tree(createTemplateMethodCall(builder, specialization, specialization.getNode().getGenericSpecialization(), specialization, null)); + builder.tree(createTemplateMethodCall(builder, specialization.getNode().getGenericSpecialization(), specialization, null)); builder.end(); // return } @@ -1202,7 +1230,7 @@ if (next != null) { returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); } - builder.tree(createGuardAndCast(builder, null, specialization, specialization, false, executeNode, returnSpecialized)); + builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized)); } private CodeTree createDeoptimize(CodeTreeBuilder parent) { @@ -1225,7 +1253,7 @@ builder.startCall(factoryClassName(node), "specialize"); builder.string("this"); builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); - addInternalValueParameterNames(builder, specialization, null, false, true); + addInternalValueParameterNames(builder, specialization, null, true, true); builder.end(); // call replace, call specialize } else { builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); @@ -1263,7 +1291,7 @@ builder.end().end(); } else { builder.startReturn(); - builder.tree(createTemplateMethodCall(builder, specialization, specialization, specialization, null)); + builder.tree(createTemplateMethodCall(builder, specialization, specialization, null)); builder.end(); // return } @@ -1294,7 +1322,7 @@ private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { for (TemplateMethod listener : node.getSpecializationListeners()) { builder.startStatement(); - builder.tree(createTemplateMethodCall(builder, listener, listener, listener, null)); + builder.tree(createTemplateMethodCall(builder, listener, listener, null)); builder.end(); // statement } } @@ -1390,7 +1418,7 @@ builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); - builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); + builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); builder.end(); // statement @@ -1443,7 +1471,7 @@ builder.startStatement(); builder.startCall("replace"); builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); - addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false, true); + addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, true, true); builder.end(); builder.end(); // call replace builder.end(); // statement diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Mon Apr 01 21:43:20 2013 +0200 @@ -313,7 +313,7 @@ private String dump(int level) { String indent = ""; for (int i = 0; i < level; i++) { - indent += " "; + indent += " "; } StringBuilder builder = new StringBuilder(); @@ -341,7 +341,7 @@ if (value instanceof List) { List list = (List) value; if (!list.isEmpty()) { - b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList((List) value))); + b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList(indent, (List) value))); } } else { if (value != null) { @@ -350,7 +350,7 @@ } } - private static String dumpList(List array) { + private static String dumpList(String indent, List array) { if (array == null) { return "null"; } @@ -364,12 +364,12 @@ StringBuilder b = new StringBuilder(); b.append("["); for (Object object : array) { - b.append("\n"); - b.append(" "); + b.append("\n "); + b.append(indent); b.append(object); b.append(", "); } - b.append("\n ]"); + b.append("\n ").append(indent).append("]"); return b.toString(); } diff -r ce6e8672f798 -r 8a1115c92271 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Mon Apr 01 21:43:20 2013 +0200 @@ -0,0 +1,130 @@ +/* + * 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.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.node.NodeFieldData.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; + +public abstract class NodeMethodParser extends TemplateMethodParser { + + public NodeMethodParser(ProcessorContext context, NodeData node) { + super(context, node); + } + + public NodeData getNode() { + return template; + } + + protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) { + ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData)); + spec.setSignature(true); + return spec; + } + + private static List nodeTypeMirrors(NodeData nodeData) { + Set typeMirrors = new LinkedHashSet<>(); + + for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { + typeMirrors.add(typeData.getType().getPrimitiveType()); + } + + typeMirrors.add(nodeData.getTypeSystem().getGenericType()); + + return new ArrayList<>(typeMirrors); + } + + protected ParameterSpec createReturnParameterSpec() { + return createValueParameterSpec("operation", getNode()); + } + + @Override + public boolean isParsable(ExecutableElement method) { + return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + } + + @SuppressWarnings("unused") + protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, String shortCircuitName) { + MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec()); + + if (getNode().supportsFrame()) { + methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); + } + + resolveAndAddImplicitThis(methodSpec, method); + + for (NodeFieldData field : getNode().getFields()) { + if (field.getKind() == FieldKind.FIELD) { + ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); + spec.setLocal(true); + methodSpec.addOptional(spec); + } + } + + for (NodeFieldData field : getNode().getFields()) { + if (field.getExecutionKind() == ExecutionKind.IGNORE) { + continue; + } + + if (field.getExecutionKind() == ExecutionKind.DEFAULT) { + ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData()); + if (field.getKind() == FieldKind.CHILDREN) { + spec.setCardinality(Cardinality.MULTIPLE); + spec.setIndexed(true); + } + methodSpec.addRequired(spec); + } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { + String valueName = field.getName(); + if (shortCircuitName != null && valueName.equals(shortCircuitName)) { + break; + } + + methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); + methodSpec.addRequired(createValueParameterSpec(valueName, field.getNodeData())); + } else { + assert false; + } + } + + return methodSpec; + } + + protected void resolveAndAddImplicitThis(MethodSpec methodSpec, ExecutableElement method) { + TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType(); + + if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(declaredType, getContext().getTruffleTypes().getNode())) { + methodSpec.addImplicitRequiredType(getNode().getTemplateType().asType()); + } + } + + private static String shortCircuitValueName(String valueName) { + return "has" + Utils.firstLetterUpperCase(valueName); + } + +} diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Mon Apr 01 21:43:20 2013 +0200 @@ -335,13 +335,7 @@ specializations.add(new SpecializationData(uninializedMethod, false, true)); } - Collections.sort(specializations, new Comparator() { - - @Override - public int compare(SpecializationData o1, SpecializationData o2) { - return compareSpecialization(o1, o2); - } - }); + Collections.sort(specializations); node.setSpecializations(specializations); @@ -372,27 +366,13 @@ for (String guardDefinition : specialization.getGuardDefinitions()) { GuardParser parser = new GuardParser(context, specialization, guardDefinition); List guards = parser.parse(methods); - Collections.sort(guards, new Comparator() { - - @Override - public int compare(GuardData o1, GuardData o2) { - int compare = o1.compareBySignature(o2); - if (compare == 0) { - compare = o1.getId().compareTo(o2.getId()); - } - if (compare == 0) { - TypeElement enclosingType1 = Utils.findNearestEnclosingType(o1.getMethod()); - TypeElement enclosingType2 = Utils.findNearestEnclosingType(o2.getMethod()); - compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString()); - } - return compare; - } - }); if (!guards.isEmpty()) { foundGuards.add(guards.get(0)); } else { // error no guard found - specialization.addError("No guard found with with name '%s'.", guardDefinition); + MethodSpec spec = parser.createSpecification(specialization.getMethod(), null); + spec.applyTypeDefinitions("types"); + specialization.addError("Guard with method name '%s' not found. Expected signature: %n%s", guardDefinition, spec.toSignatureString("guard")); } } @@ -573,17 +553,17 @@ boolean valid = true; int args = -1; for (SpecializationData specializationData : nodeData.getSpecializations()) { - int specializationArgs = 0; + int signatureArgs = 0; for (ActualParameter param : specializationData.getParameters()) { - if (!param.getSpecification().isOptional()) { - specializationArgs++; + if (param.getSpecification().isSignature()) { + signatureArgs++; } } - if (args != -1 && args != specializationArgs) { + if (args != -1 && args != signatureArgs) { valid = false; break; } - args = specializationArgs; + args = signatureArgs; } if (!valid) { for (SpecializationData specialization : nodeData.getSpecializations()) { @@ -759,7 +739,11 @@ NodeFieldData fieldData = new NodeFieldData(var, findAccessElement(var), mirror, kind, execution); if (type != null && mirror != null) { - NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(type)); + TypeElement typeElement = Utils.fromTypeMirror(type); + if (typeElement == null) { + return null; + } + NodeData fieldNodeData = resolveNode(typeElement); fieldData.setNode(fieldNodeData); if (fieldNodeData == null) { @@ -974,7 +958,7 @@ SpecializationData m1 = specializations.get(i); for (int j = i + 1; j < specializations.size(); j++) { SpecializationData m2 = specializations.get(j); - int inferredOrder = compareSpecialization(m1, m2); + int inferredOrder = m1.compareBySignature(m2); if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { int specOrder = m1.getOrder() - m2.getOrder(); @@ -1014,26 +998,6 @@ } } - private static int compareSpecialization(SpecializationData m1, SpecializationData m2) { - if (m1 == m2) { - return 0; - } - - if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { - return m1.getOrder() - m2.getOrder(); - } else if (m1.isUninitialized() ^ m2.isUninitialized()) { - return m1.isUninitialized() ? -1 : 1; - } else if (m1.isGeneric() ^ m2.isGeneric()) { - return m1.isGeneric() ? 1 : -1; - } - - if (m1.getTemplate() != m2.getTemplate()) { - throw new UnsupportedOperationException("Cannot compare two specializations with different templates."); - } - - return m1.compareBySignature(m2); - } - @Override public Class getAnnotationType() { return null; diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Mon Apr 01 21:43:20 2013 +0200 @@ -95,6 +95,31 @@ return false; } + @Override + public int compareBySignature(TemplateMethod other) { + if (this == other) { + return 0; + } else if (!(other instanceof SpecializationData)) { + return super.compareBySignature(other); + } + + SpecializationData m2 = (SpecializationData) other; + + if (getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { + return getOrder() - m2.getOrder(); + } else if (isUninitialized() ^ m2.isUninitialized()) { + return isUninitialized() ? -1 : 1; + } else if (isGeneric() ^ m2.isGeneric()) { + return isGeneric() ? 1 : -1; + } + + if (getTemplate() != m2.getTemplate()) { + throw new UnsupportedOperationException("Cannot compare two specializations with different templates."); + } + + return super.compareBySignature(m2); + } + public NodeData getNode() { return node; } @@ -165,4 +190,8 @@ return !getGuards().isEmpty(); } + @Override + public String toString() { + return String.format("%s [id = %s, method = %s, guards = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards()); + } } diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Mon Apr 01 21:43:20 2013 +0200 @@ -26,33 +26,74 @@ import javax.lang.model.type.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; + public class MethodSpec { - private final List implicitTypes; + private final List implicitRequiredTypes = new ArrayList<>(); private final ParameterSpec returnType; - private final List parameters; + private final List optional = new ArrayList<>(); + private final List required = new ArrayList<>(); + + private boolean variableRequiredArguments; + private List typeDefinitions; - public MethodSpec(List prefixTypes, ParameterSpec returnType, List parameters) { - this.implicitTypes = prefixTypes; + public MethodSpec(ParameterSpec returnType) { this.returnType = returnType; - this.parameters = parameters; + } + + public void setVariableRequiredArguments(boolean variableArguments) { + this.variableRequiredArguments = variableArguments; } - public List getImplicitTypes() { - return implicitTypes; + public boolean isVariableRequiredArguments() { + return variableRequiredArguments; + } + + public void addImplicitRequiredType(TypeMirror type) { + this.implicitRequiredTypes.add(type); + } + + public void addOptional(ParameterSpec spec) { + optional.add(spec); + } + + public void addRequired(ParameterSpec spec) { + required.add(spec); + } + + public List getImplicitRequiredTypes() { + return implicitRequiredTypes; } public ParameterSpec getReturnType() { return returnType; } - public List getParameters() { - return parameters; + public List getRequired() { + return required; + } + + public List getOptional() { + return optional; + } + + public void makeTypeDefinitions() { + + } + + public List getAll() { + List specs = new ArrayList<>(); + specs.add(getReturnType()); + specs.addAll(getOptional()); + specs.addAll(getRequired()); + return specs; } public ParameterSpec findParameterSpec(String name) { - for (ParameterSpec spec : parameters) { + for (ParameterSpec spec : getAll()) { if (spec.getName().equals(name)) { return spec; } @@ -60,4 +101,131 @@ return null; } + public void applyTypeDefinitions(String prefix) { + this.typeDefinitions = createTypeDefinitions(prefix); + } + + private List createTypeDefinitions(String prefix) { + List typeDefs = new ArrayList<>(); + + int defIndex = 0; + for (ParameterSpec spec : getAll()) { + List allowedTypes = spec.getAllowedTypes(); + List types = spec.getAllowedTypes(); + if (types != null && allowedTypes.size() > 1) { + TypeDef foundDef = null; + for (TypeDef def : typeDefs) { + if (allowedTypes.equals(def.getTypes())) { + foundDef = def; + break; + } + } + if (foundDef == null) { + foundDef = new TypeDef(types, prefix + defIndex); + typeDefs.add(foundDef); + defIndex++; + } + + spec.setTypeDefinition(foundDef); + } + } + + return typeDefs; + } + + public String toSignatureString(String methodName) { + StringBuilder b = new StringBuilder(); + b.append(" "); + b.append(createTypeSignature(returnType, true)); + + b.append(" "); + b.append(methodName); + b.append("("); + + String sep = ""; + + for (ParameterSpec optionalSpec : getOptional()) { + b.append(sep); + b.append("["); + b.append(createTypeSignature(optionalSpec, false)); + b.append("]"); + sep = ", "; + } + + for (ParameterSpec requiredSpec : getRequired()) { + b.append(sep); + if (requiredSpec.getCardinality() == Cardinality.MULTIPLE) { + b.append("{"); + } + b.append(createTypeSignature(requiredSpec, false)); + if (requiredSpec.getCardinality() == Cardinality.MULTIPLE) { + b.append("}"); + } + sep = ", "; + } + + b.append(")"); + + if (typeDefinitions != null && !typeDefinitions.isEmpty()) { + b.append("\n\n"); + + String lineSep = ""; + for (TypeDef def : typeDefinitions) { + b.append(lineSep); + b.append(" <").append(def.getName()).append(">"); + b.append(" = {"); + String separator = ""; + for (TypeMirror type : def.getTypes()) { + b.append(separator).append(Utils.getSimpleName(type)); + separator = ", "; + } + b.append("}"); + lineSep = "\n"; + + } + } + return b.toString(); + } + + private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) { + StringBuilder builder = new StringBuilder(); + TypeDef foundTypeDef = spec.getTypeDefinition(); + if (foundTypeDef != null) { + builder.append("<" + foundTypeDef.getName() + ">"); + } else if (spec.getAllowedTypes().size() >= 1) { + builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0))); + } else { + builder.append("void"); + } + if (!typeOnly) { + builder.append(" "); + builder.append(spec.getName()); + } + return builder.toString(); + } + + @Override + public String toString() { + return toSignatureString("methodName"); + } + + static class TypeDef { + + private final List types; + private final String name; + + public TypeDef(List types, String name) { + this.types = types; + this.name = name; + } + + public List getTypes() { + return types; + } + + public String getName() { + return name; + } + } + } diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Mon Apr 01 21:43:20 2013 +0200 @@ -27,6 +27,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.MethodSpec.TypeDef; public class ParameterSpec { @@ -38,9 +39,7 @@ private final List allowedTypes; /** Cardinality one or multiple. */ - private Cardinality cardinality; - /** Type is optional can be dismissed. */ - private boolean optional; + private Cardinality cardinality = Cardinality.ONE; /** Type is part of the method signature. Relevant for comparisons. */ private boolean signature; /** Type must be indexed when parsing. */ @@ -48,6 +47,8 @@ /** Type is bound to local final variable. */ private boolean local; + private TypeDef typeDefinition; + public ParameterSpec(String name, TypeMirror... allowedTypes) { this(name, Arrays.asList(allowedTypes)); } @@ -57,8 +58,12 @@ this.allowedTypes = allowedTypes; } - public void setOptional(boolean optional) { - this.optional = optional; + void setTypeDefinition(TypeDef typeDefinition) { + this.typeDefinition = typeDefinition; + } + + TypeDef getTypeDefinition() { + return typeDefinition; } public void setSignature(boolean signature) { @@ -93,10 +98,6 @@ return name; } - public boolean isOptional() { - return optional; - } - public Cardinality getCardinality() { return cardinality; } @@ -114,4 +115,25 @@ return false; } + @Override + public String toString() { + return toSignatureString(false); + } + + public String toSignatureString(boolean typeOnly) { + StringBuilder builder = new StringBuilder(); + if (typeDefinition != null) { + builder.append("<" + typeDefinition.getName() + ">"); + } else if (getAllowedTypes().size() >= 1) { + builder.append(Utils.getSimpleName(getAllowedTypes().get(0))); + } else { + builder.append("void"); + } + if (!typeOnly) { + builder.append(" "); + builder.append(getName()); + } + return builder.toString(); + } + } diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Mon Apr 01 21:43:20 2013 +0200 @@ -30,7 +30,10 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.typesystem.*; -public class TemplateMethod extends MessageContainer { +/** + * Note: this class has a natural ordering that is inconsistent with equals. + */ +public class TemplateMethod extends MessageContainer implements Comparable { private String id; private final Template template; @@ -38,7 +41,7 @@ private final ExecutableElement method; private final AnnotationMirror markerAnnotation; private final ActualParameter returnType; - private final List parameters; + private List parameters; public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, List parameters) { @@ -62,6 +65,10 @@ getMessages().addAll(method.getMessages()); } + public void setParameters(List parameters) { + this.parameters = parameters; + } + @Override public Element getMessageElement() { return method; @@ -97,6 +104,16 @@ return returnType; } + public List getRequiredParameters() { + List requiredParameters = new ArrayList<>(); + for (ActualParameter parameter : getParameters()) { + if (getSpecification().getRequired().contains(parameter.getSpecification())) { + requiredParameters.add(parameter); + } + } + return requiredParameters; + } + public List getParameters() { return parameters; } @@ -117,15 +134,6 @@ return Collections.unmodifiableList(allParameters); } - public ActualParameter findParameter(ParameterSpec spec) { - for (ActualParameter param : getParameters()) { - if (param.getSpecification().getName().equals(spec.getName())) { - return param; - } - } - return null; - } - public boolean canBeAccessedByInstanceOf(TypeMirror type) { TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType(); return Utils.isAssignable(type, methodType) || Utils.isAssignable(methodType, type); @@ -149,7 +157,7 @@ @Override public String toString() { - return "id = " + getId() + ", " + getClass().getSimpleName() + " [method = " + getMethod() + "]"; + return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod()); } public ActualParameter getPreviousParam(ActualParameter searchParam) { @@ -177,6 +185,26 @@ return types; } + @Override + public int compareTo(TemplateMethod o) { + if (this == o) { + return 0; + } + + int compare = compareBySignature(o); + if (compare == 0) { + // if signature sorting failed sort by id + compare = getId().compareTo(o.getId()); + } + if (compare == 0) { + // if still no difference sort by enclosing type name + TypeElement enclosingType1 = Utils.findNearestEnclosingType(getMethod()); + TypeElement enclosingType2 = Utils.findNearestEnclosingType(o.getMethod()); + compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString()); + } + return compare; + } + public int compareBySignature(TemplateMethod compareMethod) { TypeSystemData typeSystem = getTemplate().getTypeSystem(); if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { @@ -186,7 +214,7 @@ List signature1 = getSignature(typeSystem); List signature2 = compareMethod.getSignature(typeSystem); if (signature1.size() != signature2.size()) { - return signature1.size() - signature2.size(); + return signature2.size() - signature1.size(); } int result = 0; @@ -194,7 +222,7 @@ int typeResult = compareActualParameter(typeSystem, signature1.get(i), signature2.get(i)); if (result == 0) { result = typeResult; - } else if (Math.signum(result) != Math.signum(typeResult)) { + } else if (typeResult != 0 && Math.signum(result) != Math.signum(typeResult)) { // We cannot define an order. return 0; } diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Mon Apr 01 21:43:20 2013 +0200 @@ -110,13 +110,7 @@ valid = false; } } - Collections.sort(parsedMethods, new Comparator() { - - @Override - public int compare(TemplateMethod o1, TemplateMethod o2) { - return o1.getMethodName().compareTo(o2.getMethodName()); - } - }); + Collections.sort(parsedMethods); if (!valid && parseNullOnError) { return null; @@ -130,27 +124,25 @@ return null; } + methodSpecification.applyTypeDefinitions("types"); + String id = method.getSimpleName().toString(); AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class); if (idAnnotation != null) { id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); } - List typeDefs = createTypeDefinitions(methodSpecification.getReturnType(), methodSpecification.getParameters()); - ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); - List parameterSpecs = new ArrayList<>(); - parameterSpecs.addAll(methodSpecification.getParameters()); ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); if (returnTypeMirror == null) { if (emitErrors) { E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); - String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true); + String expectedReturnType = returnTypeSpec.toSignatureString(true); String actualReturnType = Utils.getSimpleName(method.getReturnType()); String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, - createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); + methodSpecification.toSignatureString(method.getSimpleName().toString())); invalidMethod.addError(message); return invalidMethod; } else { @@ -163,12 +155,12 @@ parameterTypes.add(var.asType()); } - List parameters = parseParameters(parameterTypes, methodSpecification.getImplicitTypes(), parameterSpecs); + List parameters = parseParameters(methodSpecification, parameterTypes); if (parameters == null) { if (isEmitErrors()) { E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method), - createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); + methodSpecification.toSignatureString(method.getSimpleName().toString())); invalidMethod.addError(message); return invalidMethod; } else { @@ -180,87 +172,95 @@ } private static String createActualSignature(MethodSpec spec, ExecutableElement method) { - List types = new ArrayList<>(); - for (TypeMirror implicitType : spec.getImplicitTypes()) { - types.add("implicit " + Utils.getSimpleName(implicitType)); + StringBuilder b = new StringBuilder("("); + String sep = ""; + for (TypeMirror implicitType : spec.getImplicitRequiredTypes()) { + b.append(sep); + b.append("implicit " + Utils.getSimpleName(implicitType)); + sep = ", "; } for (VariableElement var : method.getParameters()) { - types.add(Utils.getSimpleName(var.asType())); - } - - StringBuilder b = new StringBuilder("("); - for (Iterator iterator = types.iterator(); iterator.hasNext();) { - b.append(iterator.next()); - if (iterator.hasNext()) { - b.append(", "); - } + b.append(sep); + b.append(Utils.getSimpleName(var.asType())); + sep = ", "; } b.append(")"); return b.toString(); } - private List parseParameters(List types, List implicitTypes, List parameterSpecs) { - Iterator parameterIterator = types.iterator(); - Iterator implicitParametersIterator = implicitTypes.iterator(); - Iterator specificationIterator = parameterSpecs.iterator(); + private List parseParameters(MethodSpec spec, List parameterTypes) { + List parsedParams = new ArrayList<>(); + ConsumableListIterator types = new ConsumableListIterator<>(parameterTypes); - TypeMirror parameter = parameterIterator.hasNext() ? parameterIterator.next() : null; - TypeMirror implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null; - ParameterSpec specification = specificationIterator.hasNext() ? specificationIterator.next() : null; + // parse optional parameters + ConsumableListIterator optionals = new ConsumableListIterator<>(spec.getOptional()); + for (TypeMirror type : types) { + int oldIndex = types.getIndex(); + int optionalCount = 1; + for (ParameterSpec paramspec : optionals) { + ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, false); + if (optionalParam != null) { + optionals.consume(optionalCount); + types.consume(); + parsedParams.add(optionalParam); + break; + } + optionalCount++; + } + if (oldIndex == types.getIndex()) { + // nothing found anymore skip optional + break; + } + } + + List typesWithImplicit = new ArrayList<>(spec.getImplicitRequiredTypes()); + typesWithImplicit.addAll(types.toList()); + types = new ConsumableListIterator<>(typesWithImplicit); int specificationParameterIndex = 0; - List resolvedParameters = new ArrayList<>(); - while (parameter != null || specification != null || implicitParameter != null) { - if (parameter == null || specification == null) { - if (specification != null && (specification.isOptional() || specification.getCardinality() == Cardinality.MULTIPLE)) { - specification = specificationIterator.hasNext() ? specificationIterator.next() : null; + ConsumableListIterator required = new ConsumableListIterator<>(spec.getRequired()); + while (required.get() != null || types.get() != null) { + if (required.get() == null || types.get() == null) { + if (required.get() != null && required.get().getCardinality() == Cardinality.MULTIPLE) { + required.consume(); specificationParameterIndex = 0; continue; } - return null; + break; } - - ActualParameter resolvedParameter = null; - - boolean implicit = false; - if (implicitParameter != null) { - resolvedParameter = matchParameter(specification, implicitParameter, template, specificationParameterIndex, true); - if (resolvedParameter != null) { - implicit = true; - } - } - - if (resolvedParameter == null) { - resolvedParameter = matchParameter(specification, parameter, template, specificationParameterIndex, false); - } - + boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); + ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit); if (resolvedParameter == null) { - // mismatch - if (specification.isOptional()) { - specification = specificationIterator.hasNext() ? specificationIterator.next() : null; - specificationParameterIndex = 0; - } else { - return null; + if (required.get().getCardinality() == Cardinality.MULTIPLE) { + required.consume(); + continue; } + // direct mismatch but required -> error + return null; } else { - resolvedParameters.add(resolvedParameter); - - // match - if (implicit) { - implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null; - } else { - parameter = parameterIterator.hasNext() ? parameterIterator.next() : null; - } - - if (specification.getCardinality() == Cardinality.ONE) { - specification = specificationIterator.hasNext() ? specificationIterator.next() : null; + parsedParams.add(resolvedParameter); + types.consume(); + if (required.get().getCardinality() == Cardinality.ONE) { + required.consume(); specificationParameterIndex = 0; - } else if (specification.getCardinality() == Cardinality.MULTIPLE) { + } else if (required.get().getCardinality() == Cardinality.MULTIPLE) { specificationParameterIndex++; } } } - return resolvedParameters; + + if (!types.toList().isEmpty()) { + // additional types -> error + return null; + } + + if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) { + // additional specifications -> error + return null; + } + + // success! + return parsedParams; } private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean implicit) { @@ -275,143 +275,53 @@ return new ActualParameter(specification, resolvedType, index, implicit); } - protected List createTypeDefinitions(ParameterSpec returnType, List parameters) { - List typeDefs = new ArrayList<>(); + /* Helper class for parsing. */ + private static class ConsumableListIterator implements Iterable { - List allParams = new ArrayList<>(); - allParams.add(returnType); - allParams.addAll(parameters); + private final List data; + private int index; + + public ConsumableListIterator(List data) { + this.data = data; + } - int defIndex = 0; - for (ParameterSpec spec : allParams) { - List allowedTypes = spec.getAllowedTypes(); - List types = spec.getAllowedTypes(); - if (types != null && allowedTypes.size() > 1) { - TypeDef foundDef = null; - for (TypeDef def : typeDefs) { - if (allowedTypes.equals(def.getTypes())) { - foundDef = def; - break; - } - } - if (foundDef == null) { - foundDef = new TypeDef(types, "Types" + defIndex); - typeDefs.add(foundDef); - defIndex++; - } + public E get() { + if (index >= data.size()) { + return null; + } + return data.get(index); + } - foundDef.getParameters().add(spec); + public E consume() { + return consume(1); + } + + public E consume(int count) { + if (index + count <= data.size()) { + index += count; + return get(); + } else { + throw new ArrayIndexOutOfBoundsException(count + 1); } } - return typeDefs; - } - - protected static class TypeDef { - - private final List types; - private final String name; - private final List parameters = new ArrayList<>(); - - public TypeDef(List types, String name) { - this.types = types; - this.name = name; + public int getIndex() { + return index; } - public List getParameters() { - return parameters; - } - - public List getTypes() { - return types; + @Override + public Iterator iterator() { + return toList().iterator(); } - public String getName() { - return name; - } - } - - public static String createExpectedSignature(String methodName, ParameterSpec returnType, List parameters, List typeDefs) { - StringBuilder b = new StringBuilder(); - - b.append(" "); - b.append(createTypeSignature(returnType, typeDefs, true)); - - b.append(" "); - b.append(methodName); - b.append("("); - - for (int i = 0; i < parameters.size(); i++) { - ParameterSpec specification = parameters.get(i); - if (specification.isOptional()) { - b.append("["); + public List toList() { + if (index < data.size()) { + return data.subList(index, data.size()); + } else { + return Collections. emptyList(); } - if (specification.getCardinality() == Cardinality.MULTIPLE) { - b.append("{"); - } - - b.append(createTypeSignature(specification, typeDefs, false)); - - if (specification.isOptional()) { - b.append("]"); - } - - if (specification.getCardinality() == Cardinality.MULTIPLE) { - b.append("}"); - } - - if (i < parameters.size() - 1) { - b.append(", "); - } - } - b.append(")"); - - if (!typeDefs.isEmpty()) { - b.append("\n\n"); - - String lineSep = ""; - for (TypeDef def : typeDefs) { - b.append(lineSep); - b.append(" <").append(def.getName()).append(">"); - b.append(" = {"); - String separator = ""; - for (TypeMirror type : def.getTypes()) { - b.append(separator).append(Utils.getSimpleName(type)); - separator = ", "; - } - b.append("}"); - lineSep = "\n"; - - } - } - return b.toString(); - } - - private static String createTypeSignature(ParameterSpec spec, List typeDefs, boolean typeOnly) { - StringBuilder builder = new StringBuilder(); - if (spec.getAllowedTypes().size() > 1) { - TypeDef foundTypeDef = null; - for (TypeDef typeDef : typeDefs) { - if (typeDef.getParameters().contains(spec)) { - foundTypeDef = typeDef; - break; - } - } - if (foundTypeDef != null) { - builder.append("<" + foundTypeDef.getName() + ">"); - } - } else if (spec.getAllowedTypes().size() == 1) { - builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0))); - } else { - builder.append("void"); - } - if (!typeOnly) { - builder.append(" "); - builder.append(spec.getName()); - } - return builder.toString(); } } diff -r ce6e8672f798 -r 8a1115c92271 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java Mon Apr 01 21:43:20 2013 +0200 @@ -22,12 +22,20 @@ */ package com.oracle.truffle.codegen.processor.typesystem; +import com.oracle.truffle.codegen.processor.node.*; import com.oracle.truffle.codegen.processor.template.*; public class GuardData extends TemplateMethod { - public GuardData(TemplateMethod method) { + private final SpecializationData specialization; + + public GuardData(TemplateMethod method, SpecializationData specialization) { super(method); + this.specialization = specialization; + } + + public SpecializationData getSpecialization() { + return specialization; } } diff -r ce6e8672f798 -r 8a1115c92271 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Mon Apr 01 21:43:20 2013 +0200 @@ -26,7 +26,6 @@ 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.node.*; @@ -47,15 +46,22 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - List specs = new ArrayList<>(); - for (ActualParameter parameter : specialization.getParameters()) { - ParameterSpec spec = new ParameterSpec(parameter.getSpecification().getName(), parameter.getActualType()); - spec.setSignature(true); - spec.setOptional(true); - specs.add(spec); + MethodSpec spec = createDefaultMethodSpec(method, mirror, null); + spec.setVariableRequiredArguments(true); + spec.getRequired().clear(); + + for (ActualParameter parameter : specialization.getRequiredParameters()) { + ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getActualType(), getNode().getTypeSystem().getGenericType()); + paramSpec.setSignature(true); + spec.addRequired(paramSpec); } - ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class)); - return new MethodSpec(Collections. emptyList(), returnTypeSpec, specs); + + return spec; + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return new ParameterSpec("returnType", getContext().getType(boolean.class)); } @Override @@ -65,7 +71,23 @@ @Override public GuardData create(TemplateMethod method) { - return new GuardData(method); + GuardData guard = new GuardData(method, specialization); + /* + * Update parameters in way that parameter specifications match again the node field names + * etc. + */ + List newParameters = new ArrayList<>(); + for (ActualParameter parameter : guard.getParameters()) { + ActualParameter specializationParameter = specialization.findParameter(parameter.getSpecification().getName()); + if (specializationParameter == null) { + newParameters.add(parameter); + } else { + newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getActualType(), specializationParameter.getIndex(), parameter.isImplicit())); + } + } + guard.setParameters(newParameters); + + return guard; } @Override diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Mon Apr 01 21:43:20 2013 +0200 @@ -23,10 +23,8 @@ package com.oracle.truffle.codegen.processor.typesystem; import java.lang.annotation.*; -import java.util.*; import javax.lang.model.element.*; -import javax.lang.model.type.*; import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; @@ -44,14 +42,8 @@ if (targetType == null) { return null; } - List specs = new ArrayList<>(); - ParameterSpec valueSpec = new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()); - valueSpec.setSignature(true); - specs.add(valueSpec); - - ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetType.getPrimitiveType()); - returnTypeSpec.setSignature(true); - MethodSpec spec = new MethodSpec(Collections. emptyList(), returnTypeSpec, specs); + MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType())); + spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors())); return spec; } diff -r ce6e8672f798 -r 8a1115c92271 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 Mon Apr 01 12:19:15 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Mon Apr 01 21:43:20 2013 +0200 @@ -23,10 +23,8 @@ package com.oracle.truffle.codegen.processor.typesystem; import java.lang.annotation.*; -import java.util.*; import javax.lang.model.element.*; -import javax.lang.model.type.*; import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; @@ -44,13 +42,8 @@ if (targetType == null) { return null; } - List specs = new ArrayList<>(); - ParameterSpec valueSpec = new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()); - valueSpec.setSignature(true); - specs.add(valueSpec); - ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class)); - returnTypeSpec.setSignature(true); - MethodSpec spec = new MethodSpec(Collections. emptyList(), returnTypeSpec, specs); + MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class))); + spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors())); return spec; }