# HG changeset patch # User Christian Humer # Date 1372785719 -7200 # Node ID b8fe1fe004ec915627d5dcc7d44671cec30359e2 # Parent 5acc3f3016b7ced09abaeaa1d42e3e00c2d306cd Truffle-DSL: fixed bugs in the generated polymorphic code generation. diff -r 5acc3f3016b7 -r b8fe1fe004ec 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 Tue Jul 02 14:51:22 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Jul 02 19:21:59 2013 +0200 @@ -79,7 +79,7 @@ } String name = Utils.firstLetterUpperCase(nodeid); - if (specialization == node.getGenericPolymorphicSpecializtion()) { + if (specialization == node.getGenericPolymorphicSpecialization()) { name += "PolymorphicNode"; } else { name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node"; @@ -101,7 +101,7 @@ private static String executeCachedName(SpecializationData polymorphic) { NodeData node = polymorphic.getNode(); - boolean generic = polymorphic == node.getGenericPolymorphicSpecializtion(); + boolean generic = polymorphic == node.getGenericPolymorphicSpecialization(); if (generic) { return "executeCachedGeneric0"; @@ -116,7 +116,7 @@ if (specialization == polymorphic) { break; } - if (specialization != node.getGenericPolymorphicSpecializtion()) { + if (specialization != node.getGenericPolymorphicSpecialization()) { index++; } } @@ -687,10 +687,10 @@ if (node.getPolymorphicDepth() > 1) { PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode, true); - add(generic, node.getGenericPolymorphicSpecializtion()); + add(generic, node.getGenericPolymorphicSpecialization()); for (SpecializationData specialization : node.getPolymorphicSpecializations()) { - if (specialization == node.getGenericPolymorphicSpecializtion()) { + if (specialization == node.getGenericPolymorphicSpecialization()) { continue; } add(new PolymorphicNodeFactory(context, generic.getElement(), false), specialization); @@ -1094,10 +1094,10 @@ clazz.add(createCreateSpecialization(node)); - CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecializtion(), null); + CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization(), null); clazz.add(genericCachedExecute); for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { - if (polymorph == node.getGenericPolymorphicSpecializtion()) { + if (polymorph == node.getGenericPolymorphicSpecialization()) { continue; } clazz.add(createCachedExecute(node, polymorph, genericCachedExecute)); @@ -1214,10 +1214,10 @@ CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); addInternalValueParameters(cachedExecute, polymorph, true, true); - if (polymorph == node.getGenericPolymorphicSpecializtion()) { + if (polymorph == node.getGenericPolymorphicSpecialization()) { cachedExecute.getModifiers().add(ABSTRACT); } else { - SpecializationData genericPolymorph = node.getGenericPolymorphicSpecializtion(); + SpecializationData genericPolymorph = node.getGenericPolymorphicSpecialization(); 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()); @@ -1378,6 +1378,7 @@ DeclaredType annotationType; if (child.getCardinality() == Cardinality.MANY) { + var.getModifiers().add(Modifier.FINAL); annotationType = getContext().getTruffleTypes().getChildrenAnnotation(); } else { annotationType = getContext().getTruffleTypes().getChildAnnotation(); @@ -1415,26 +1416,31 @@ List specializations = node.getSpecializations(); + boolean firstUnreachable = true; + SpecializationData previous = null; for (SpecializationData current : specializations) { - if (current.isUninitialized() || !current.isReachable()) { + if (current.isUninitialized()) { continue; } - CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.tree(createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current)); + if (current.isReachable()) { + CodeTree execute = createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current); - if (!current.isGeneric()) { - builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end(); - } + if (!current.isGeneric()) { + builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end(); + } - builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false)); - } - - for (SpecializationData current : specializations) { - if (current.isUninitialized() || current.isReachable()) { - continue; + builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute, null, true, false)); + } else { + if (firstUnreachable) { + if (previous != null && !previous.isGenericSpecialization(getContext()) && !previous.hasRewrite(getContext())) { + emitEncounteredSynthetic(builder, current); + } + firstUnreachable = false; + } + builder.string("// unreachable ").string(current.getId()).newLine(); } - builder.string("// unreachable ").string(current.getId()).newLine(); + previous = current; } return method; @@ -1527,7 +1533,7 @@ builder.startWhile().string("searchNode != null").end(); builder.startBlock(); builder.statement("searchNode = searchNode.getParent()"); - builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion())).end(); + builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end(); builder.startBlock().breakStatement().end(); builder.end(); builder.startStatement().startCall("searchNode", "replace"); @@ -1586,15 +1592,26 @@ } private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { - String className = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion()); + String className = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization()); CodeTreeBuilder builder = parent.create(); builder.startStatement(); builder.string(className); builder.string(" polymorphic = "); builder.startNew(className).string("this").end(); builder.end(); - for (NodeChildData child : node.getChildren()) { - builder.startStatement().string("this.").string(child.getName()).string(" = null").end(); + + for (ActualParameter param : node.getGenericSpecialization().getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + NodeChildData child = node.findChild(param.getSpecification().getName()); + if (child != null) { + builder.startStatement().string("this.").string(child.getName()); + if (child.getCardinality().isMany()) { + builder.string("[").string(String.valueOf(param.getIndex())).string("]"); + } + builder.string(" = null").end(); + } } builder.startStatement().startCall("super", "replace"); builder.string("polymorphic"); @@ -1814,7 +1831,7 @@ builder.tree(createDeoptimize(builder)); builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); if (specialization.isPolymorphic()) { - builder.tree(createReturnOptimizeTypes(builder, specialization, param)); + builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); } else { builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); @@ -1825,10 +1842,10 @@ return builder.getRoot(); } - private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) { + private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) { NodeData node = specialization.getNode(); assert !node.getPolymorphicSpecializations().isEmpty(); - SpecializationData generic = node.getGenericPolymorphicSpecializtion(); + SpecializationData generic = node.getGenericPolymorphicSpecialization(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); builder.startReturn(); @@ -1839,9 +1856,8 @@ execute.end(); TypeData sourceType = generic.getReturnType().getTypeSystemType(); - TypeData targetType = specialization.getReturnType().getTypeSystemType(); - builder.tree(createCastType(node, sourceType, targetType, true, execute.getRoot())); + builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot())); builder.end(); return builder.getRoot(); @@ -1875,6 +1891,7 @@ if (!parameter.getSpecification().isSignature()) { builder.string(parameter.getLocalName()); } else { + if (index < targetField.getExecuteWith().size()) { NodeChildData child = targetField.getExecuteWith().get(index); @@ -2201,7 +2218,7 @@ private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { NodeData node = specialization.getNode(); - String genericClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion()); + String genericClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization()); CodeTreeBuilder builder = new CodeTreeBuilder(parent); builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); diff -r 5acc3f3016b7 -r b8fe1fe004ec 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 Tue Jul 02 14:51:22 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Tue Jul 02 19:21:59 2013 +0200 @@ -47,7 +47,7 @@ private List specializations; private List polymorphicSpecializations; - private SpecializationData genericPolymoprhicSpecialization; + private SpecializationData genericPolymorphicSpecialization; private List specializationListeners; private Map> executableTypes; private List shortCircuits; @@ -522,12 +522,12 @@ return polymorphicSpecializations; } - void setGenericPolymoprhicSpecialization(SpecializationData genericPolymoprhicSpecialization) { - this.genericPolymoprhicSpecialization = genericPolymoprhicSpecialization; + void setGenericPolymorphicSpecialization(SpecializationData genericPolymoprhicSpecialization) { + this.genericPolymorphicSpecialization = genericPolymoprhicSpecialization; } - public SpecializationData getGenericPolymorphicSpecializtion() { - return genericPolymoprhicSpecialization; + public SpecializationData getGenericPolymorphicSpecialization() { + return genericPolymorphicSpecialization; } void setSpecializationListeners(List specializationListeners) { diff -r 5acc3f3016b7 -r b8fe1fe004ec 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 Tue Jul 02 14:51:22 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Tue Jul 02 19:21:59 2013 +0200 @@ -255,6 +255,14 @@ SpecializationData generic = node.getGenericSpecialization(); for (Signature signature : sortedSignatures) { SpecializationData specialization = new SpecializationData(generic, false, false, true); + + for (Iterator iterator = specialization.getParameters().iterator(); iterator.hasNext();) { + ActualParameter param = iterator.next(); + if (param.getSpecification().isLocal()) { + iterator.remove(); + } + } + specialization.forceFrame(context.getTruffleTypes().getFrame()); specialization.setNode(node); specialization.updateSignature(signature); @@ -265,7 +273,7 @@ } } - node.setGenericPolymoprhicSpecialization(polymorphicGeneric); + node.setGenericPolymorphicSpecialization(polymorphicGeneric); node.setPolymorphicSpecializations(specializations); } @@ -575,36 +583,7 @@ } else if (generics.size() == 1) { genericSpecialization = generics.get(0); } else if (node.needsRewrites(context)) { - SpecializationData specialization = specializations.get(0); - GenericParser parser = new GenericParser(context, node); - MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); - - ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context, 0); - assert anyGenericReturnType != null; - - ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType(), 0, false); - List parameters = new ArrayList<>(); - for (ActualParameter specializationParameter : specialization.getParameters()) { - ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName()); - NodeChildData child = node.findChild(parameterSpec.getName()); - TypeData actualType; - if (child == null) { - actualType = specializationParameter.getTypeSystemType(); - } else { - ExecutableTypeData paramType = child.findAnyGenericExecutableType(context); - assert paramType != null; - actualType = paramType.getType(); - } - - if (actualType != null) { - parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isImplicit())); - } else { - parameters.add(new ActualParameter(parameterSpec, specializationParameter.getType(), specializationParameter.getIndex(), specializationParameter.isImplicit())); - } - } - TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); - genericSpecialization = new SpecializationData(genericMethod, true, false, false); - + genericSpecialization = createGenericSpecialization(node, specializations); specializations.add(genericSpecialization); } @@ -684,6 +663,57 @@ } } + private SpecializationData createGenericSpecialization(final NodeData node, List specializations) { + SpecializationData genericSpecialization; + SpecializationData specialization = specializations.get(0); + GenericParser parser = new GenericParser(context, node); + MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); + + List parameters = new ArrayList<>(); + for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) { + if (!parameter.getSpecification().isSignature()) { + parameters.add(new ActualParameter(parameter)); + continue; + } + NodeData childNode = node; + NodeChildData child = node.findChild(parameter.getSpecification().getName()); + if (child != null) { + childNode = child.getNodeData(); + } + + TypeData genericType = null; + + Set types = new HashSet<>(); + for (SpecializationData otherSpecialization : specializations) { + ActualParameter otherParameter = otherSpecialization.findParameter(parameter.getLocalName()); + if (otherParameter != null) { + types.add(otherParameter.getTypeSystemType()); + } + } + + assert !types.isEmpty(); + + if (types.size() == 1) { + ExecutableTypeData executable = childNode.findExecutableType(types.iterator().next(), 0); + if (executable != null && !executable.hasUnexpectedValue(context)) { + genericType = types.iterator().next(); + } else { + genericType = childNode.findAnyGenericExecutableType(context, 0).getType(); + } + } else { + genericType = childNode.findAnyGenericExecutableType(context, 0).getType(); + } + + parameters.add(new ActualParameter(parameter, genericType)); + } + ActualParameter returnType = parameters.get(0); + parameters = parameters.subList(1, parameters.size()); + + TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); + genericSpecialization = new SpecializationData(genericMethod, true, false, false); + return genericSpecialization; + } + private void assignShortCircuitsToSpecializations(NodeData node) { Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); diff -r 5acc3f3016b7 -r b8fe1fe004ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Tue Jul 02 14:51:22 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Tue Jul 02 19:21:59 2013 +0200 @@ -107,7 +107,8 @@ if (child == null) { continue; } - if (!parameter.getTypeSystemType().isGeneric()) { + ActualParameter genericParameter = getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); + if (!parameter.getTypeSystemType().equals(genericParameter.getTypeSystemType())) { return false; } } @@ -223,6 +224,16 @@ this.assumptions = assumptions; } + public SpecializationData findPreviousSpecialization() { + List specializations = node.getSpecializations(); + for (int i = 0; i < specializations.size() - 1; i++) { + if (specializations.get(i) == this && i > 0) { + return specializations.get(i - 1); + } + } + return null; + } + public SpecializationData findNextSpecialization() { List specializations = node.getSpecializations(); for (int i = 0; i < specializations.size() - 1; i++) { diff -r 5acc3f3016b7 -r b8fe1fe004ec 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 Tue Jul 02 14:51:22 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Tue Jul 02 19:21:59 2013 +0200 @@ -28,7 +28,6 @@ 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.*; /** @@ -141,7 +140,7 @@ public List findParameters(ParameterSpec spec) { List foundParameters = new ArrayList<>(); for (ActualParameter param : getReturnTypeAndParameters()) { - if (param.getSpecification().equals(spec)) { + if (param.getSpecification().getName().equals(spec.getName())) { foundParameters.add(param); } }