Mercurial > hg > graal-compiler
changeset 11458:906d0cdf9c51
Merge
author | Christos Kotselidis <christos.kotselidis@oracle.com> |
---|---|
date | Thu, 29 Aug 2013 17:17:35 +0200 |
parents | fd1383d45420 (current diff) bd1a12a78a51 (diff) |
children | c66cdfb7445b df18a4214c7c |
files | |
diffstat | 11 files changed, 276 insertions(+), 303 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Thu Aug 29 17:17:35 2013 +0200 @@ -47,12 +47,18 @@ public long y = 10; } + public static class C extends B { + + public long z = 5; + } + public static long test1Snippet(A a) { - B b = (B) a; - long ret = b.x; // this can be moved before the checkcast - ret += b.y; + C c = (C) a; + long ret = c.x; // this can be pushed before the checkcast + ret += c.y; // not allowed to push + ret += c.z; // not allowed to push // the null-check should be canonicalized with the null-check of the checkcast - ret += b != null ? 100 : 200; + ret += c != null ? 100 : 200; return ret; } @@ -64,24 +70,20 @@ public void run() { StructuredGraph graph = compileTestSnippet(snippet); - int counter = 0; for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) { if (rn.location() instanceof ConstantLocationNode && rn.object().stamp() instanceof ObjectStamp) { long disp = ((ConstantLocationNode) rn.location()).getDisplacement(); ResolvedJavaType receiverType = ObjectStamp.typeOrNull(rn.object()); ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp); - if (field != null) { - if (field.getName().equals("x")) { - Assert.assertTrue(rn.object() instanceof LocalNode); - } else { - Assert.assertTrue(rn.object().toString(), rn.object() instanceof PiNode); - } - counter++; + assert field != null : "Node " + rn + " tries to access a field which doesn't exists for this type"; + if (field.getName().equals("x")) { + Assert.assertTrue(rn.object() instanceof LocalNode); + } else { + Assert.assertTrue(rn.object().toString(), rn.object() instanceof PiNode); } } } - Assert.assertEquals(2, counter); Assert.assertTrue(graph.getNodes().filter(IsNullNode.class).count() == 1); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Thu Aug 29 17:17:35 2013 +0200 @@ -236,6 +236,7 @@ HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); new InliningPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase(true).apply(graph, context); new PartialEscapePhase(iterativeEscapeAnalysis).apply(graph, context); Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Thu Aug 29 17:17:35 2013 +0200 @@ -124,6 +124,45 @@ } } + @Test + public void testCache() { + testMaterialize("testCacheSnippet", 0.5, 1); + } + + public static class CacheKey { + + private final int idx; + private final Object ref; + + public CacheKey(int idx, Object ref) { + this.idx = idx; + this.ref = ref; + } + + @Override + public int hashCode() { + return 31 * idx + ref.hashCode(); + } + + public synchronized boolean equals(CacheKey other) { + return idx == other.idx && ref == other.ref; + } + } + + public static CacheKey cacheKey = null; + public static Object value = null; + + private static native Object createValue(CacheKey key); + + public static Object testCacheSnippet(int idx, Object ref) { + CacheKey key = new CacheKey(idx, ref); + if (!key.equals(cacheKey)) { + cacheKey = key; + value = createValue(key); + } + return value; + } + @SafeVarargs final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) { StructuredGraph result = processMethod(snippet); @@ -162,15 +201,14 @@ HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); new InliningPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); - canonicalizer.apply(graph, context); + new CanonicalizerPhase(true).apply(graph, context); new PartialEscapePhase(false).apply(graph, context); for (MergeNode merge : graph.getNodes(MergeNode.class)) { merge.setStateAfter(null); } new DeadCodeEliminationPhase().apply(graph); - canonicalizer.apply(graph, context); + new CanonicalizerPhase(true).apply(graph, context); return graph; } });
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu Aug 29 17:17:35 2013 +0200 @@ -104,29 +104,31 @@ @Override public boolean push(PiNode parent) { - if (location() instanceof ConstantLocationNode) { - long displacement = ((ConstantLocationNode) location()).getDisplacement(); - if (parent.stamp() instanceof ObjectStamp) { - ObjectStamp piStamp = (ObjectStamp) parent.stamp(); - ResolvedJavaType receiverType = piStamp.type(); - if (receiverType != null) { - ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement); + if (!(location() instanceof ConstantLocationNode && parent.stamp() instanceof ObjectStamp && parent.object().stamp() instanceof ObjectStamp)) { + return false; + } + + ObjectStamp piStamp = (ObjectStamp) parent.stamp(); + ResolvedJavaType receiverType = piStamp.type(); + if (receiverType == null) { + return false; + } - if (field != null && parent.object().stamp() instanceof ObjectStamp) { - ResolvedJavaType declaringClass = field.getDeclaringClass(); - ObjectStamp piValueStamp = (ObjectStamp) parent.object().stamp(); - ResolvedJavaType piValueType = ObjectStamp.typeOrNull(piValueStamp); - if (piValueType != null && declaringClass.isAssignableFrom(piValueType)) { - if (piStamp.nonNull() == piValueStamp.nonNull() && piStamp.alwaysNull() == piValueStamp.alwaysNull()) { - replaceFirstInput(parent, parent.object()); - return true; - } - } - } - } + ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(((ConstantLocationNode) location()).getDisplacement()); + if (field == null) { + // field was not declared by receiverType + return false; + } + + ObjectStamp valueStamp = (ObjectStamp) parent.object().stamp(); + ResolvedJavaType valueType = ObjectStamp.typeOrNull(valueStamp); + if (valueType != null && field.getDeclaringClass().isAssignableFrom(valueType)) { + if (piStamp.nonNull() == valueStamp.nonNull() && piStamp.alwaysNull() == valueStamp.alwaysNull()) { + replaceFirstInput(parent, parent.object()); + return true; } + } - } return false; }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Thu Aug 29 17:17:35 2013 +0200 @@ -233,6 +233,8 @@ if (node == beginNode) { loweringTool.setLastFixedNode(beginNode); } else { + assert !(node instanceof Lowerable) : "SchedulingError: Lowerable " + node + " should not float before begin node " + beginNode; + assert node instanceof FloatingNode : "skipped node must be a FloatingNode: " + node; continue; } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java Thu Aug 29 17:17:35 2013 +0200 @@ -133,6 +133,8 @@ return Kind.Long; case Int: return Kind.Int; + case Byte: + return Kind.Byte; case Double: return Kind.Double; case Float:
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Thu Aug 29 17:17:35 2013 +0200 @@ -26,13 +26,8 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.DoubleEvaluatedNodeFactory; -import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.EvaluatedNodeFactory; -import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluatedNodeFactory; -import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestArguments; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.*; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -104,4 +99,31 @@ } } + @Test + public void testEvaluatedGeneration() throws UnexpectedResultException { + TestRootNode<TestEvaluatedGeneration> root = TestHelper.createRoot(TestEvaluatedGenerationFactory.getInstance()); + + Assert.assertEquals(42, root.getNode().executeEvaluated1(null, 42)); + Assert.assertEquals(42, root.getNode().executeEvaluated2(null, 42)); + Assert.assertEquals(42, root.getNode().executeEvaluated3(null, 42)); + Assert.assertEquals(42, root.getNode().executeEvaluated4(null, 42)); + } + + @NodeChildren({@NodeChild("exp0")}) + abstract static class TestEvaluatedGeneration extends ValueNode { + + public abstract Object executeEvaluated1(VirtualFrame frame, Object value); + + public abstract Object executeEvaluated2(VirtualFrame frame, int value); + + public abstract int executeEvaluated3(VirtualFrame frame, Object value) throws UnexpectedResultException; + + public abstract int executeEvaluated4(VirtualFrame frame, int value) throws UnexpectedResultException; + + @Specialization + int call(int exp0) { + return exp0; + } + } + }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Thu Aug 29 17:17:35 2013 +0200 @@ -47,12 +47,13 @@ List<ParameterSpec> requiredSpecs = new ArrayList<>(spec.getRequired()); spec.getRequired().clear(); + List<TypeMirror> allowedTypes = getNode().getTypeSystem().getPrimitiveTypeMirrors(); for (ParameterSpec originalSpec : requiredSpecs) { - spec.addRequired(new ParameterSpec(originalSpec, Arrays.asList(getNode().getTypeSystem().getGenericType()))); + spec.addRequired(new ParameterSpec(originalSpec, allowedTypes)); } spec.setVariableRequiredArguments(true); - ParameterSpec other = new ParameterSpec("other", Arrays.asList(getNode().getTypeSystem().getGenericType())); + ParameterSpec other = new ParameterSpec("other", allowedTypes); other.setCardinality(Cardinality.MANY); other.setSignature(true); other.setIndexed(true);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Thu Aug 29 17:17:35 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); @@ -1918,9 +1765,15 @@ } } + // execute names are enforced no cast + String[] executeParameterNames = new String[executeParameters.size()]; + for (int i = 0; i < executeParameterNames.length; i++) { + executeParameterNames[i] = valueName(executeParameters.get(i)); + } + builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true)); - CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null); + CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames); if (needsTry) { if (!returnVoid) { builder.declaration(primaryType.getPrimitiveType(), "value"); @@ -2011,6 +1864,7 @@ ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); String targetVariableName = valueName(targetParameter); + CodeTree executionExpression = null; if ((sourceParameter != null && cast) || sourceParameter != null) { TypeData sourceType = sourceParameter.getTypeSystemType(); @@ -2020,7 +1874,7 @@ } builder.startStatement(); builder.type(targetParameter.getType()).string(" "); - builder.string(valueName(targetParameter)).string(" = "); + builder.string(targetVariableName).string(" = "); builder.tree(CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter))); builder.end(); continue; @@ -2055,10 +1909,6 @@ cast = true; } - if (specialization.isGeneric() && unexpected) { - throw new AssertionError("Generic has unexpected parameters. " + specialization.toString()); - } - builder.startStatement(); if (!shortCircuit) { @@ -2459,7 +2309,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 +2330,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 +2476,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 +2484,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 +2493,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 Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Thu Aug 29 17:17:35 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) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Thu Aug 29 16:23:14 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Thu Aug 29 17:17:35 2013 +0200 @@ -193,10 +193,50 @@ return b.toString(); } + /* + * Parameter parsing tries to parse required arguments starting from offset 0 with increasing + * offset until it finds a signature end that matches the required specification. If there is no + * end matching the required arguments, parsing fails. Parameters prior to the parsed required + * ones are cut and used to parse the optional parameters. All those remaining parameters must + * be consumed otherwise its an error. + */ private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes) { + List<TypeMirror> implicitTypes = spec.getImplicitRequiredTypes(); + + int offset = -1; + List<ActualParameter> parsedRequired = null; + ConsumableListIterator<TypeMirror> types = null; + while (parsedRequired == null && offset < parameterTypes.size()) { + offset++; + types = new ConsumableListIterator<>(new ArrayList<>(implicitTypes)); + types.data.addAll(parameterTypes.subList(offset, parameterTypes.size())); + parsedRequired = parseParametersRequired(spec, types); + } + + if (parsedRequired == null && offset >= 0) { + return null; + } + + List<TypeMirror> potentialOptionals; + if (offset == -1) { + potentialOptionals = parameterTypes; + } else { + potentialOptionals = parameterTypes.subList(0, offset); + } + types = new ConsumableListIterator<>(potentialOptionals); + List<ActualParameter> parsedOptionals = parseParametersOptional(spec, types); + if (parsedOptionals == null) { + return null; + } + + List<ActualParameter> finalParameters = new ArrayList<>(); + finalParameters.addAll(parsedOptionals); + finalParameters.addAll(parsedRequired); + return finalParameters; + } + + private List<ActualParameter> parseParametersOptional(MethodSpec spec, ConsumableListIterator<TypeMirror> types) { List<ActualParameter> parsedParams = new ArrayList<>(); - ConsumableListIterator<TypeMirror> types = new ConsumableListIterator<>(parameterTypes); - // parse optional parameters ConsumableListIterator<ParameterSpec> optionals = new ConsumableListIterator<>(spec.getOptional()); for (TypeMirror type : types) { @@ -217,10 +257,14 @@ break; } } + if (types.getIndex() <= types.data.size() - 1) { + return null; + } + return parsedParams; + } - List<TypeMirror> typesWithImplicit = new ArrayList<>(spec.getImplicitRequiredTypes()); - typesWithImplicit.addAll(types.toList()); - types = new ConsumableListIterator<>(typesWithImplicit); + private List<ActualParameter> parseParametersRequired(MethodSpec spec, ConsumableListIterator<TypeMirror> types) { + List<ActualParameter> parsedParams = new ArrayList<>(); int specificationParameterIndex = 0; ConsumableListIterator<ParameterSpec> required = new ConsumableListIterator<>(spec.getRequired()); @@ -263,8 +307,6 @@ // additional specifications -> error return null; } - - // success! return parsedParams; }