Mercurial > hg > truffle
diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 10600:e93efe3ba5f4
Truffle-DSL: rewritten polymorphic optimization for simpler generated code.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 02 Jul 2013 14:51:05 +0200 |
parents | 79041ab43660 |
children | b8fe1fe004ec |
line wrap: on
line diff
--- 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<NodeData> { @@ -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<SpecializationData> 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()) {