# HG changeset patch # User Christian Humer # Date 1372769465 -7200 # Node ID e93efe3ba5f470a50105dedb0a89c8aa87bccad0 # Parent ebf5c5c2356401b7e3327bc0204b49886ee7b637 Truffle-DSL: rewritten polymorphic optimization for simpler generated code. diff -r ebf5c5c23564 -r e93efe3ba5f4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Mon Jul 01 21:08:20 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Jul 02 14:51:05 2013 +0200 @@ -35,8 +35,10 @@ import com.oracle.truffle.api.nodes.NodeInfo.Kind; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.ast.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; +import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; +import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.template.TemplateMethod.*; import com.oracle.truffle.dsl.processor.typesystem.*; public class NodeCodeGenerator extends CompilationUnitFactory { @@ -77,11 +79,10 @@ } String name = Utils.firstLetterUpperCase(nodeid); - int index = specialization == null ? 0 : node.getPolymorphicSpecializations().indexOf(specialization); - if (index == 0) { + if (specialization == node.getGenericPolymorphicSpecializtion()) { name += "PolymorphicNode"; } else { - name += "Polymorphic" + index + "Node"; + name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node"; } return name; } @@ -98,6 +99,30 @@ return valueName(parameter) + "Cast"; } + private static String executeCachedName(SpecializationData polymorphic) { + NodeData node = polymorphic.getNode(); + boolean generic = polymorphic == node.getGenericPolymorphicSpecializtion(); + + if (generic) { + return "executeCachedGeneric0"; + } else { + return "executeCached" + polymorphicIndex(node, polymorphic); + } + } + + private static int polymorphicIndex(NodeData node, SpecializationData polymorphic) { + int index = 0; + for (SpecializationData specialization : node.getPolymorphicSpecializations()) { + if (specialization == polymorphic) { + break; + } + if (specialization != node.getGenericPolymorphicSpecializtion()) { + index++; + } + } + return index; + } + private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) { if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); @@ -660,15 +685,17 @@ createFactoryMethods(node, clazz, createVisibility); - PolymorphicNodeFactory generic = null; - for (SpecializationData specialization : node.getPolymorphicSpecializations()) { - PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(context, generic == null ? generatedNode : generic.getElement(), generic == null); - add(polymorphicFactory, specialization); - if (generic == null) { - generic = polymorphicFactory; + if (node.getPolymorphicDepth() > 1) { + PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode, true); + add(generic, node.getGenericPolymorphicSpecializtion()); + + for (SpecializationData specialization : node.getPolymorphicSpecializations()) { + if (specialization == node.getGenericPolymorphicSpecializtion()) { + continue; + } + add(new PolymorphicNodeFactory(context, generic.getElement(), false), specialization); } } - for (SpecializationData specialization : node.getSpecializations()) { if (!specialization.isReachable()) { continue; @@ -1044,10 +1071,6 @@ return clazz; } - protected String typeGetterName(ActualParameter parameter) { - return "get" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type"; - } - @Override protected void createChildren(SpecializationData specialization) { NodeData node = specialization.getNode(); @@ -1067,17 +1090,17 @@ builder.statement("this.next0 = adoptChild(next0)"); clazz.add(setter); - createTypeGetters(clazz, node.getGenericSpecialization()); + createIsCompatible(clazz, null); clazz.add(createCreateSpecialization(node)); - CodeExecutableElement genericCachedExecute = null; + CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecializtion(), null); + clazz.add(genericCachedExecute); for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { - CodeExecutableElement cachedExecute = createCachedExecute(node, polymorph, genericCachedExecute); - clazz.add(cachedExecute); - if (genericCachedExecute == null) { - genericCachedExecute = cachedExecute; + if (polymorph == node.getGenericPolymorphicSpecializtion()) { + continue; } + clazz.add(createCachedExecute(node, polymorph, genericCachedExecute)); } } @@ -1142,31 +1165,59 @@ return method; } - protected void createTypeGetters(CodeTypeElement clazz, SpecializationData specialization) { - for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; + protected void createIsCompatible(CodeTypeElement clazz, SpecializationData specialization) { + CodeExecutableElement isCompatible = new CodeExecutableElement(modifiers(PROTECTED), context.getType(boolean.class), "isCompatible0"); + isCompatible.addParameter(new CodeVariableElement(getContext().getType(Class.class), "type")); + + if (specialization == null) { + isCompatible.getModifiers().add(ABSTRACT); + } else if (specialization.isGeneric()) { + isCompatible.createBuilder().startThrow().startNew(getContext().getType(AssertionError.class)).end().end(); + } else if (specialization.isPolymorphic()) { + isCompatible.createBuilder().startReturn().string("type != getClass() && next0.isCompatible0(type)").end(); + } else if (specialization.isUninitialized()) { + isCompatible.createBuilder().returnTrue(); + } else { + NodeData node = specialization.getNode(); + CodeTreeBuilder builder = isCompatible.createBuilder(); + + Signature specializationSignature = specialization.getSignature(); + List compatible = new ArrayList<>(); + for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { + if (specializationSignature.isCompatibleTo(polymorphic.getSignature())) { + compatible.add(polymorphic); + } } - CodeExecutableElement typeGetter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(Class.class), typeGetterName(parameter)); - CodeTreeBuilder builder = typeGetter.createBuilder(); - builder.startReturn().typeLiteral(parameter.getType()).end(); - clazz.add(typeGetter); + + if (compatible.isEmpty()) { + builder.returnFalse(); + } else { + builder.startIf(); + String and = ""; + for (SpecializationData polymorphic : compatible) { + builder.string(and); + builder.string("type == ").string(nodePolymorphicClassName(node, polymorphic)).string(".class"); + and = " || "; + } + builder.end().startBlock(); + builder.startReturn().startCall("next0", "isCompatible0").string("type").end().end(); + builder.end(); + builder.returnFalse(); + } } + + clazz.add(isCompatible); } private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) { - int index = node.getPolymorphicSpecializations().indexOf(polymorph); - assert index != -1; - boolean generic = index == 0; - - String name = "executeCached" + index; + String name = executeCachedName(polymorph); CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); addInternalValueParameters(cachedExecute, polymorph, true, true); - if (generic) { + if (polymorph == node.getGenericPolymorphicSpecializtion()) { cachedExecute.getModifiers().add(ABSTRACT); } else { - SpecializationData genericPolymorph = node.getPolymorphicSpecializations().get(0); + SpecializationData genericPolymorph = node.getGenericPolymorphicSpecializtion(); CodeTreeBuilder builder = cachedExecute.createBuilder(); ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType()); ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType()); @@ -1476,7 +1527,7 @@ builder.startWhile().string("searchNode != null").end(); builder.startBlock(); builder.statement("searchNode = searchNode.getParent()"); - builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getPolymorphicSpecializations().get(0))).end(); + builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion())).end(); builder.startBlock().breakStatement().end(); builder.end(); builder.startStatement().startCall("searchNode", "replace"); @@ -1535,11 +1586,12 @@ } private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { + String className = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion()); CodeTreeBuilder builder = parent.create(); builder.startStatement(); - builder.string(nodePolymorphicClassName(node, null)); + builder.string(className); builder.string(" polymorphic = "); - builder.startNew(nodePolymorphicClassName(node, null)).string("this").end(); + builder.startNew(className).string("this").end(); builder.end(); for (NodeChildData child : node.getChildren()) { builder.startStatement().string("this.").string(child.getName()).string(" = null").end(); @@ -1776,13 +1828,13 @@ private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) { NodeData node = specialization.getNode(); assert !node.getPolymorphicSpecializations().isEmpty(); - SpecializationData generic = node.getPolymorphicSpecializations().get(0); + SpecializationData generic = node.getGenericPolymorphicSpecializtion(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); builder.startReturn(); CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.startCall("next0", "executeCached0"); + execute.startCall("next0", executeCachedName(generic)); addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true); execute.end(); @@ -1965,7 +2017,6 @@ @Override protected void createChildren(SpecializationData specialization) { -// super.createChildren(specialization); CodeTypeElement clazz = getElement(); createConstructors(clazz); @@ -1974,6 +2025,7 @@ if (generic) { getElement().add(createOptimizeTypes()); createCachedExecuteMethods(specialization); + createIsCompatible(clazz, specialization); } } @@ -1981,65 +2033,31 @@ NodeData node = getModel().getNode(); CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes"); CodeTreeBuilder builder = method.createBuilder(); - builder.startStatement().string(baseClassName(node)).string(" node = this.next0").end(); - TypeMirror classType = getContext().getType(Class.class); - - SpecializationData genericSpecialization = node.getGenericSpecialization(); - - CodeTreeBuilder whileBodyBuilder = builder.create(); - for (ActualParameter parameter : node.getGenericSpecialization().getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - - ActualParameter genericParameter = genericSpecialization.findParameter(parameter.getLocalName()); - - String name = parameter.getLocalName() + "Type"; - - builder.declaration(classType, name, builder.create().startCall("node", typeGetterName(parameter)).end().getRoot()); - - whileBodyBuilder.startIf().string(name).string(" != ").startCall("node", typeGetterName(parameter)).end().end(); - whileBodyBuilder.startBlock(); - whileBodyBuilder.startStatement().string(name).string(" = ").typeLiteral(genericParameter.getType()).end(); - whileBodyBuilder.end(); - } - - builder.startWhile().string("node != null && !(").instanceOf("node", nodeSpecializationClassName(node.getUninitializedSpecialization())).string(")").end(); - builder.startBlock(); - builder.tree(whileBodyBuilder.getRoot()); - builder.statement("node = node.next0"); - builder.end(); boolean elseIf = false; - for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { - elseIf = builder.startIf(elseIf); - String and = ""; + for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { + String className = nodePolymorphicClassName(node, polymorphic); + + String sep = ""; StringBuilder reason = new StringBuilder("Optimized polymorphic types for ("); - for (ActualParameter parameter : polymorph.getReturnTypeAndParameters()) { + for (ActualParameter parameter : polymorphic.getReturnTypeAndParameters()) { if (!parameter.getSpecification().isSignature()) { continue; } - String name = parameter.getLocalName() + "Type"; - builder.string(and).string(name).string(" == ").typeLiteral(parameter.getType()); - - if (!and.isEmpty()) { - reason.append(", "); - } - reason.append(Utils.getSimpleName(parameter.getType())); - and = " && "; + reason.append(sep).append(Utils.getSimpleName(parameter.getType())); + sep = ", "; } reason.append(")"); - builder.end(); - builder.startBlock(); - String className = nodePolymorphicClassName(node, polymorph); - builder.startIf().string("getClass() != ").string(className).string(".class").end(); - builder.startBlock(); + elseIf = builder.startIf(elseIf); + builder.startCall("isCompatible0"); + builder.startGroup().string(className).string(".class").end(); + builder.end().end().startBlock(); + builder.startStatement().startCall("super", "replace"); builder.startNew(className).string("this").end(); builder.doubleQuote(reason.toString()); builder.end().end(); // call - builder.end(); // block builder.end(); } return method; @@ -2098,9 +2116,8 @@ NodeData node = specialization.getNode(); - if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic() && node.needsRewrites(getContext()) && node.getPolymorphicDepth() > 1) { - - createTypeGetters(clazz, specialization); + if (node.needsRewrites(getContext()) && node.getPolymorphicDepth() > 1) { + createIsCompatible(clazz, specialization); } createExecuteMethods(specialization); @@ -2152,45 +2169,39 @@ protected void createCachedExecuteMethods(SpecializationData specialization) { NodeData node = specialization.getNode(); CodeTypeElement clazz = getElement(); - int index = 0; for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { - boolean matchFound = false; - if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic()) { - matchFound = polymorphic.getSignature().hasAnyParameterMatch(specialization.getSignature()); + if (!specialization.getSignature().isCompatibleTo(polymorphic.getSignature())) { + continue; } + ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic)); + ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); - if (matchFound || index == 0) { - ExecutableElement executeCached = nodeGen.getMethod("executeCached" + index); - ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); - - CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); - CodeTreeBuilder builder = executeMethod.createBuilder(); + CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); + CodeTreeBuilder builder = executeMethod.createBuilder(); - if (specialization.isGeneric() || specialization.isPolymorphic()) { - builder.startThrow().startNew(getContext().getType(AssertionError.class)); - builder.doubleQuote("Should not be reached."); - builder.end().end(); - } else if (specialization.isUninitialized()) { - builder.tree(createAppendPolymorphic(builder, specialization)); - } else { - CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); - elseBuilder.startReturn().startCall("this.next0", "executeCached" + index); - addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true); - elseBuilder.end().end(); - CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.tree(createGenericInvoke(builder, polymorphic, specialization)); - boolean forceElse = !specialization.getExceptions().isEmpty(); - builder.tree(createGuardAndCast(builder, null, polymorphic, specialization, true, execute.getRoot(), elseBuilder.getRoot(), true, forceElse)); - } - clazz.add(executeMethod); + if (specialization.isGeneric() || specialization.isPolymorphic()) { + builder.startThrow().startNew(getContext().getType(AssertionError.class)); + builder.doubleQuote("Should not be reached."); + builder.end().end(); + } else if (specialization.isUninitialized()) { + builder.tree(createAppendPolymorphic(builder, specialization)); + } else { + CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); + elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); + addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true); + elseBuilder.end().end(); + CodeTreeBuilder execute = new CodeTreeBuilder(builder); + execute.tree(createGenericInvoke(builder, polymorphic, specialization)); + boolean forceElse = !specialization.getExceptions().isEmpty(); + builder.tree(createGuardAndCast(builder, null, polymorphic, specialization, true, execute.getRoot(), elseBuilder.getRoot(), true, forceElse)); } - index++; + clazz.add(executeMethod); } } private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { NodeData node = specialization.getNode(); - String genericClassName = nodePolymorphicClassName(node, null); + String genericClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion()); CodeTreeBuilder builder = new CodeTreeBuilder(parent); builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); @@ -2376,11 +2387,7 @@ CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); if (specialization.isPolymorphic()) { - int index = 0; - if (executable.hasUnexpectedValue(getContext())) { - index = specialization.getNode().getPolymorphicSpecializations().indexOf(specialization); - } - returnBuilder.startCall("next0", "executeCached" + index); + returnBuilder.startCall("next0", executeCachedName(specialization)); addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); returnBuilder.end(); } else if (specialization.isUninitialized()) { diff -r ebf5c5c23564 -r e93efe3ba5f4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Mon Jul 01 21:08:20 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Tue Jul 02 14:51:05 2013 +0200 @@ -47,6 +47,7 @@ private List specializations; private List polymorphicSpecializations; + private SpecializationData genericPolymoprhicSpecialization; private List specializationListeners; private Map> executableTypes; private List shortCircuits; @@ -521,6 +522,14 @@ return polymorphicSpecializations; } + void setGenericPolymoprhicSpecialization(SpecializationData genericPolymoprhicSpecialization) { + this.genericPolymoprhicSpecialization = genericPolymoprhicSpecialization; + } + + public SpecializationData getGenericPolymorphicSpecializtion() { + return genericPolymoprhicSpecialization; + } + void setSpecializationListeners(List specializationListeners) { this.specializationListeners = specializationListeners; } diff -r ebf5c5c23564 -r e93efe3ba5f4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Mon Jul 01 21:08:20 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Tue Jul 02 14:51:05 2013 +0200 @@ -33,9 +33,10 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; +import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; +import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.template.TemplateMethod.*; +import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; import com.oracle.truffle.dsl.processor.typesystem.*; public class NodeParser extends TemplateParser { @@ -200,7 +201,7 @@ for (NodeData splittedNode : nodes) { finalizeSpecializations(elements, splittedNode); verifyNode(splittedNode, elements); - splittedNode.setPolymorphicSpecializations(createPolymorphicSpecializations(splittedNode)); + createPolymorphicSpecializations(splittedNode); assignShortCircuitsToSpecializations(splittedNode); } @@ -212,13 +213,14 @@ return node; } - private List createPolymorphicSpecializations(NodeData node) { + private void createPolymorphicSpecializations(NodeData node) { if (!node.needsRewrites(context) || node.getPolymorphicDepth() <= 1) { - return Collections.emptyList(); + node.setPolymorphicSpecializations(Collections. emptyList()); + return; } Signature genericSignature = node.getGenericSpecialization().getSignature(); - Set signatures = new HashSet<>(); + Set signatures = new TreeSet<>(); for (SpecializationData specialization1 : node.getSpecializations()) { Signature signature = specialization1.getSignature(); @@ -247,8 +249,8 @@ } List sortedSignatures = new ArrayList<>(signatures); - Collections.sort(sortedSignatures); + SpecializationData polymorphicGeneric = null; List specializations = new ArrayList<>(); SpecializationData generic = node.getGenericSpecialization(); for (Signature signature : sortedSignatures) { @@ -256,15 +258,15 @@ specialization.forceFrame(context.getTruffleTypes().getFrame()); specialization.setNode(node); specialization.updateSignature(signature); + specializations.add(specialization); - if (specialization.isGenericSpecialization(context)) { - specializations.add(0, specialization); - } else { - specializations.add(specialization); + if (genericSignature.equals(signature)) { + polymorphicGeneric = specialization; } } - return specializations; + node.setGenericPolymoprhicSpecialization(polymorphicGeneric); + node.setPolymorphicSpecializations(specializations); } private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List elements, List lookupTypes) { @@ -1071,7 +1073,7 @@ } private static Map> groupExecutableTypes(List executableTypes) { - Map> groupedTypes = new HashMap<>(); + Map> groupedTypes = new TreeMap<>(); for (ExecutableTypeData type : executableTypes) { int evaluatedCount = type.getEvaluatedCount(); diff -r ebf5c5c23564 -r e93efe3ba5f4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Mon Jul 01 21:08:20 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Tue Jul 02 14:51:05 2013 +0200 @@ -28,6 +28,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; import com.oracle.truffle.dsl.processor.typesystem.*; /** @@ -315,23 +316,6 @@ return types.hashCode(); } - public int compareTo(Signature o) { - if (o.size() != size()) { - return size() - o.size(); - } - - int typeSum = 0; - int otherTypeSum = 0; - for (int i = 0; i < types.size(); i++) { - TypeData type = types.get(i); - TypeData otherType = o.get(i); - typeSum += type.isGeneric() ? 1 : 0; - otherTypeSum += otherType.isGeneric() ? 1 : 0; - } - - return typeSum - otherTypeSum; - } - public int size() { return types.size(); } @@ -340,6 +324,28 @@ return types.get(index); } + public int compareTo(Signature other) { + if (this == other) { + return 0; + } else if (types.size() != other.types.size()) { + return types.size() - other.types.size(); + } else if (types.isEmpty()) { + return 0; + } + + for (int i = 0; i < types.size(); i++) { + TypeData type1 = types.get(i); + TypeData type2 = other.types.get(i); + + int comparison = type1.compareTo(type2); + if (comparison != 0) { + return comparison; + } + } + + return 0; + } + public Signature combine(Signature genericSignature, Signature other) { assert types.size() == other.types.size(); assert genericSignature.types.size() == other.types.size(); @@ -388,6 +394,25 @@ } return false; } + + public boolean isCompatibleTo(Signature signature) { + if (size() != signature.size()) { + return false; + } + + for (int i = 0; i < size(); i++) { + TypeData o1 = get(i); + TypeData o2 = signature.get(i); + if (o1.equals(o2)) { + continue; + } else if (o2.isGeneric()) { + continue; + } else { + return false; + } + } + return true; + } } } diff -r ebf5c5c23564 -r e93efe3ba5f4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java Mon Jul 01 21:08:20 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java Tue Jul 02 14:51:05 2013 +0200 @@ -30,17 +30,19 @@ import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.template.*; -public class TypeData extends MessageContainer { +public class TypeData extends MessageContainer implements Comparable { private final TypeSystemData typeSystem; private final AnnotationValue annotationValue; private final TypeMirror primitiveType; private final TypeMirror boxedType; + private final int index; private final List typeCasts = new ArrayList<>(); private final List typeChecks = new ArrayList<>(); - public TypeData(TypeSystemData typeSystem, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { + public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { + this.index = index; this.typeSystem = typeSystem; this.annotationValue = value; this.primitiveType = primitiveType; @@ -101,6 +103,13 @@ return Utils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType()); } + public int compareTo(TypeData o) { + if (this.equals(o)) { + return 0; + } + return index - o.index; + } + @Override public String toString() { return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]"; diff -r ebf5c5c23564 -r e93efe3ba5f4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Mon Jul 01 21:08:20 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Tue Jul 02 14:51:05 2013 +0200 @@ -76,7 +76,7 @@ } TypeMirror genericType = context.getType(Object.class); - TypeData voidType = new TypeData(typeSystem, null, context.getType(void.class), context.getType(Void.class)); + TypeData voidType = new TypeData(typeSystem, typeSystem.getTypes().size(), null, context.getType(void.class), context.getType(Void.class)); typeSystem.setGenericType(genericType); typeSystem.setVoidType(voidType); @@ -151,9 +151,10 @@ final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value"); final TypeMirror objectType = context.getType(Object.class); + int index = 0; for (TypeMirror primitiveType : typeMirrors) { TypeMirror boxedType = Utils.boxType(context, primitiveType); - TypeData typeData = new TypeData(typeSystem, annotationValue, primitiveType, boxedType); + TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitiveType, boxedType); if (isPrimitiveWrapper(primitiveType)) { typeData.addError("Types must not contain primitive wrapper types."); @@ -164,11 +165,12 @@ } types.add(typeData); + index++; } verifyTypeOrder(types); - types.add(new TypeData(typeSystem, annotationValue, objectType, objectType)); + types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType)); return types; }