# HG changeset patch # User Christos Kotselidis # Date 1377789455 -7200 # Node ID 906d0cdf9c515af4be250964e211d51e6f849798 # Parent fd1383d4542029d6ab3dc8bf0b4cfb1d2adcc205# Parent bd1a12a78a5176aae8a1e29aadf0c5f0d79eced2 Merge diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java --- 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); } diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- 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(); diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- 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... 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; } }); diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- 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; } diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- 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; } } diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java --- 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: diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java --- 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 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; + } + } + } diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java --- 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 requiredSpecs = new ArrayList<>(spec.getRequired()); spec.getRequired().clear(); + List 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); diff -r fd1383d45420 -r 906d0cdf9c51 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 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 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 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); - } - /** *
      * 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 guardedblock) {
-            return guard(outerParent, source, group, checkMinimumState, new CodeBlock() {
-
-                public CodeTree create(CodeTreeBuilder parent, Void value) {
+        protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState,
+                        final CodeBlock guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions) {
+            return guard(outerParent, source, group, checkMinimumState, new CodeBlock() {
+
+                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 bodyBlock) {
+        private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock 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() {
+
+                        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() {
+
+                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
+                    return createExecute(b, executable, specialization);
+                }
+            }, returnSpecialized, false, false));
 
             return builder.getRoot();
         }
diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java
--- 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 specializations) {
         List groups = new ArrayList<>();
         for (SpecializationData specialization : specializations) {
diff -r fd1383d45420 -r 906d0cdf9c51 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java
--- 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 parseParameters(MethodSpec spec, List parameterTypes) {
+        List implicitTypes = spec.getImplicitRequiredTypes();
+
+        int offset = -1;
+        List parsedRequired = null;
+        ConsumableListIterator 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 potentialOptionals;
+        if (offset == -1) {
+            potentialOptionals = parameterTypes;
+        } else {
+            potentialOptionals = parameterTypes.subList(0, offset);
+        }
+        types = new ConsumableListIterator<>(potentialOptionals);
+        List parsedOptionals = parseParametersOptional(spec, types);
+        if (parsedOptionals == null) {
+            return null;
+        }
+
+        List finalParameters = new ArrayList<>();
+        finalParameters.addAll(parsedOptionals);
+        finalParameters.addAll(parsedRequired);
+        return finalParameters;
+    }
+
+    private List parseParametersOptional(MethodSpec spec, ConsumableListIterator types) {
         List parsedParams = new ArrayList<>();
-        ConsumableListIterator types = new ConsumableListIterator<>(parameterTypes);
-
         // parse optional parameters
         ConsumableListIterator 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 typesWithImplicit = new ArrayList<>(spec.getImplicitRequiredTypes());
-        typesWithImplicit.addAll(types.toList());
-        types = new ConsumableListIterator<>(typesWithImplicit);
+    private List parseParametersRequired(MethodSpec spec, ConsumableListIterator types) {
+        List parsedParams = new ArrayList<>();
 
         int specificationParameterIndex = 0;
         ConsumableListIterator required = new ConsumableListIterator<>(spec.getRequired());
@@ -263,8 +307,6 @@
             // additional specifications -> error
             return null;
         }
-
-        // success!
         return parsedParams;
     }