Mercurial > hg > graal-compiler
changeset 11443:b33783cbd8ce
Truffle-DSL: refactored redundant guard generation code.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Wed, 28 Aug 2013 11:41:10 +0200 |
parents | 2868b55001d4 |
children | 89febfdb81d2 |
files | graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java |
diffstat | 2 files changed, 103 insertions(+), 245 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Wed Aug 28 01:45:13 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Wed Aug 28 11:41:10 2013 +0200 @@ -324,223 +324,6 @@ body.string(".").startCall(methodName); } - private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues, - CodeTree guardedStatements, CodeTree elseStatements, boolean emitAssumptions, boolean forceElse) { - - NodeData node = targetSpecialization.getNode(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization, emitAssumptions); - CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization); - - Set<String> 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 targetParameter : guard.getParameters()) { - NodeChildData field = node.findChild(targetParameter.getSpecification().getName()); - if (field == null) { - continue; - } - TypeData targetType = targetParameter.getTypeSystemType(); - ActualParameter sourceParameter = sourceSpecialization.findParameter(targetParameter.getLocalName()); - if (sourceParameter == null) { - sourceParameter = targetParameter; - } - TypeData sourceType = sourceParameter.getTypeSystemType(); - - if (sourceType.needsCastTo(getContext(), targetType)) { - valuesNeedsCast.add(targetParameter.getLocalName()); - } - } - } - } - - int ifCount = 0; - - if (implicitGuards != null) { - builder.startIf(); - builder.tree(implicitGuards); - builder.end(); - builder.startBlock(); - ifCount++; - } - - builder.tree(createCasts(parent, valuesNeedsCast, sourceSpecialization, targetSpecialization)); - - if (explicitGuards != null) { - builder.startIf(); - builder.tree(explicitGuards); - builder.end(); - builder.startBlock(); - ifCount++; - } - - if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) { - builder.startIf(); - builder.string(conditionPrefix); - builder.end().startBlock(); - ifCount++; - } - - builder.tree(guardedStatements); - - builder.end(ifCount); - if (elseStatements != null && (forceElse || ifCount > 0)) { - builder.tree(elseStatements); - } - return builder.getRoot(); - } - - private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; - if (guardedSpecialization.getGuards().size() > 0) { - // Explicitly specified guards - for (GuardData guard : guardedSpecialization.getGuards()) { - builder.string(andOperator); - if (guard.isNegated()) { - builder.string("!"); - } - builder.tree(createTemplateMethodCall(parent, null, valueSpecialization, guard, null)); - andOperator = " && "; - } - } - - return builder.isEmpty() ? null : builder.getRoot(); - } - - private CodeTree createCasts(CodeTreeBuilder parent, Set<String> castWhiteList, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - // Implict guards based on method signature - for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { - NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); - if (field == null) { - continue; - } - ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); - - if (valueParam == null) { - /* - * If used inside a function execute method. The value param may not exist. In that - * case it assumes that the value is already converted. - */ - valueParam = guardedParam; - } - - if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) { - continue; - } - - CodeTree cast = createCast(parent, field, valueParam, guardedParam.getTypeSystemType()); - if (cast == null) { - continue; - } - builder.tree(cast); - } - - return builder.getRoot(); - } - - private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean emitAssumptions) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - // Implict guards based on method signature - String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; - - if (emitAssumptions) { - for (String assumption : guardedSpecialization.getAssumptions()) { - builder.string(andOperator); - builder.string("this"); - builder.string(".").string(assumption).string(".isValid()"); - andOperator = " && "; - } - } - - for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { - NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); - if (field == null) { - continue; - } - ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); - - if (valueParam == null) { - /* - * If used inside a function execute method. The value param may not exist. In that - * case it assumes that the value is already converted. - */ - valueParam = guardedParam; - } - - CodeTree implicitGuard = createTypeGuard(builder, field, valueParam, guardedParam.getTypeSystemType()); - if (implicitGuard == null) { - continue; - } - - builder.string(andOperator); - builder.tree(implicitGuard); - andOperator = " && "; - } - - return builder.isEmpty() ? null : builder.getRoot(); - } - - private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) { - NodeData node = field.getNodeData(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - TypeData sourceType = source.getTypeSystemType(); - - if (!sourceType.needsCastTo(getContext(), targetType)) { - return null; - } - - builder.startGroup(); - - if (field.isShortCircuit()) { - ActualParameter shortCircuit = source.getPreviousParameter(); - assert shortCircuit != null; - builder.string("("); - builder.string("!").string(valueName(shortCircuit)); - builder.string(" || "); - } - - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(targetType)); - builder.string(valueName(source)); - builder.end().end(); // call - - if (field.isShortCircuit()) { - builder.string(")"); - } - - builder.end(); // group - - return builder.getRoot(); - } - - private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) { - NodeData node = field.getNodeData(); - TypeData sourceType = source.getTypeSystemType(); - - if (!sourceType.needsCastTo(getContext(), targetType)) { - return null; - } - - CodeTree condition = null; - if (field.isShortCircuit()) { - ActualParameter shortCircuit = source.getPreviousParameter(); - assert shortCircuit != null; - condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); - } - - CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(source))); - - return createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value); - } - /** * <pre> * variant1 $condition != null @@ -1444,7 +1227,7 @@ public CodeTree create(CodeTreeBuilder b, SpecializationData current) { return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar); } - })); + }, null, false, true)); boolean firstUnreachable = true; for (SpecializationData current : node.getSpecializations()) { @@ -1488,7 +1271,7 @@ public CodeTree create(CodeTreeBuilder b, SpecializationData current) { return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current); } - })); + }, null, false, true)); emitUnreachableSpecializations(builder, node); @@ -1504,39 +1287,47 @@ } } - private CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, - final CodeBlock<SpecializationData> guardedblock) { - return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Void>() { - - public CodeTree create(CodeTreeBuilder parent, Void value) { + protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, + final CodeBlock<SpecializationData> guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions) { + return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Integer>() { + + public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { CodeTreeBuilder builder = parent.create(); if (group.getSpecialization() != null) { builder.tree(guardedblock.create(builder, group.getSpecialization())); assert group.getChildren().isEmpty() : "missed a specialization"; + } else { for (SpecializationGroup childGroup : group.getChildren()) { - builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock)); + builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions)); } } return builder.getRoot(); } - }); + }, elseBlock, forceElse, emitAssumptions); } - private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Void> bodyBlock) { + private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, + boolean forceElse, boolean emitAssumptions) { CodeTreeBuilder builder = parent.create(); - int ifCount = emitGuards(builder, source, group, checkMinimumState); + int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions); if (isReachableGroup(group, ifCount, checkMinimumState)) { - builder.tree(bodyBlock.create(builder, null)); + builder.tree(bodyBlock.create(builder, ifCount)); } builder.end(ifCount); + if (elseBlock != null) { + if (ifCount > 0 || forceElse) { + builder.tree(elseBlock); + } + } + return builder.getRoot(); } @@ -1561,7 +1352,7 @@ return true; } - private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState) { + private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions) { NodeData node = source.getNode(); CodeTreeBuilder guardsBuilder = builder.create(); @@ -1601,11 +1392,13 @@ } } - for (String assumption : group.getAssumptions()) { - guardsBuilder.string(guardsAnd); - guardsBuilder.string("this"); - guardsBuilder.string(".").string(assumption).string(".isValid()"); - guardsAnd = " && "; + if (emitAssumptions) { + for (String assumption : group.getAssumptions()) { + guardsBuilder.string(guardsAnd); + guardsBuilder.string("this"); + guardsBuilder.string(".").string(assumption).string(".isValid()"); + guardsAnd = " && "; + } } for (TypeGuard typeGuard : group.getTypeGuards()) { @@ -1697,7 +1490,7 @@ sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); } - if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), requiredType)) { + if (Utils.needsCastTo(getContext(), sourceParameter.getType(), requiredType.getPrimitiveType())) { return true; } } @@ -1707,6 +1500,60 @@ return false; } + private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) { + NodeData node = field.getNodeData(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + TypeData sourceType = source.getTypeSystemType(); + + if (!sourceType.needsCastTo(getContext(), targetType)) { + return null; + } + + builder.startGroup(); + + if (field.isShortCircuit()) { + ActualParameter shortCircuit = source.getPreviousParameter(); + assert shortCircuit != null; + builder.string("("); + builder.string("!").string(valueName(shortCircuit)); + builder.string(" || "); + } + + startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(targetType)); + builder.string(valueName(source)); + builder.end().end(); // call + + if (field.isShortCircuit()) { + builder.string(")"); + } + + builder.end(); // group + + return builder.getRoot(); + } + + private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) { + NodeData node = field.getNodeData(); + TypeData sourceType = source.getTypeSystemType(); + + if (!sourceType.needsCastTo(getContext(), targetType)) { + return null; + } + + CodeTree condition = null; + if (field.isShortCircuit()) { + ActualParameter shortCircuit = source.getPreviousParameter(); + assert shortCircuit != null; + condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); + } + + CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(source))); + + return createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value); + } + private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) { CodeTreeBuilder builder = parent.create(); builder.string(prefix); @@ -2459,7 +2306,7 @@ protected void createCachedExecuteMethods(SpecializationData specialization) { NodeData node = specialization.getNode(); CodeTypeElement clazz = getElement(); - for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { + for (final SpecializationData polymorphic : node.getPolymorphicSpecializations()) { if (!specialization.getSignature().isCompatibleTo(polymorphic.getSignature())) { continue; } @@ -2480,10 +2327,14 @@ 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)); + + boolean forceElse = specialization.getExceptions().size() > 0; + builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { + + public CodeTree create(CodeTreeBuilder b, SpecializationData current) { + return createGenericInvoke(b, polymorphic, current); + } + }, elseBuilder.getRoot(), forceElse, true)); } clazz.add(executeMethod); } @@ -2622,7 +2473,7 @@ return filteredTypes; } - private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) { + private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final SpecializationData specialization, final ExecutableTypeData executable) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (specialization.isUninitialized()) { builder.tree(createDeoptimize(builder)); @@ -2630,8 +2481,6 @@ builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); - CodeTree executeNode = createExecute(builder, executable, specialization); - CodeTree returnSpecialized = null; if (specialization.findNextSpecialization() != null) { @@ -2641,7 +2490,12 @@ returnSpecialized = returnBuilder.getRoot(); } - builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false, false)); + builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { + + public CodeTree create(CodeTreeBuilder b, SpecializationData current) { + return createExecute(b, executable, specialization); + } + }, returnSpecialized, false, false)); return builder.getRoot(); }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Wed Aug 28 01:45:13 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Wed Aug 28 11:41:10 2013 +0200 @@ -258,6 +258,10 @@ return false; } + public static SpecializationGroup create(SpecializationData specialization) { + return new SpecializationGroup(specialization); + } + public static SpecializationGroup create(List<SpecializationData> specializations) { List<SpecializationGroup> groups = new ArrayList<>(); for (SpecializationData specialization : specializations) {