comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 11201:7fc3e1fb3965

Truffle-DSL: specialization group fixes.
author Christian Humer <christian.humer@gmail.com>
date Mon, 05 Aug 2013 19:50:34 +0200
parents 3479ab380552
children 80de3bbfa8b9
comparison
equal deleted inserted replaced
11200:380e0248f873 11201:7fc3e1fb3965
36 import com.oracle.truffle.api.nodes.*; 36 import com.oracle.truffle.api.nodes.*;
37 import com.oracle.truffle.dsl.processor.*; 37 import com.oracle.truffle.dsl.processor.*;
38 import com.oracle.truffle.dsl.processor.ast.*; 38 import com.oracle.truffle.dsl.processor.ast.*;
39 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; 39 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
40 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; 40 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind;
41 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard;
41 import com.oracle.truffle.dsl.processor.template.*; 42 import com.oracle.truffle.dsl.processor.template.*;
42 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; 43 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature;
43 import com.oracle.truffle.dsl.processor.typesystem.*; 44 import com.oracle.truffle.dsl.processor.typesystem.*;
44 45
45 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { 46 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> {
1101 @Override 1102 @Override
1102 protected void createChildren(SpecializationData specialization) { 1103 protected void createChildren(SpecializationData specialization) {
1103 NodeData node = specialization.getNode(); 1104 NodeData node = specialization.getNode();
1104 CodeTypeElement clazz = getElement(); 1105 CodeTypeElement clazz = getElement();
1105 1106
1107 SpecializationGroup rootGroup = createSpecializationGroups(node);
1108
1106 if (node.needsRewrites(context)) { 1109 if (node.needsRewrites(context)) {
1107
1108 if (node.isPolymorphic()) { 1110 if (node.isPolymorphic()) {
1109 1111
1110 CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); 1112 CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
1111 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); 1113 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
1112 clazz.add(var); 1114 clazz.add(var);
1127 } 1129 }
1128 clazz.add(createCachedExecute(node, polymorph, genericCachedExecute)); 1130 clazz.add(createCachedExecute(node, polymorph, genericCachedExecute));
1129 } 1131 }
1130 } 1132 }
1131 1133
1132 clazz.add(createGenericExecuteAndSpecialize(node)); 1134 clazz.add(createGenericExecuteAndSpecialize(node, rootGroup));
1133 clazz.add(createInfoMessage(node)); 1135 clazz.add(createInfoMessage(node));
1134 } 1136 }
1135 1137
1136 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { 1138 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
1137 clazz.add(createGenericExecute(node)); 1139 clazz.add(createGenericExecute(node, rootGroup));
1138 } 1140 }
1139 } 1141 }
1140 1142
1141 private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) { 1143 private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) {
1142 CodeTreeBuilder builder = parent.create(); 1144 CodeTreeBuilder builder = parent.create();
1413 1415
1414 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); 1416 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
1415 return var; 1417 return var;
1416 } 1418 }
1417 1419
1418 private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node) { 1420 private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node, SpecializationGroup rootGroup) {
1419 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); 1421 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1420 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME); 1422 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME);
1421 method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState")); 1423 method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState"));
1422 addInternalValueParameters(method, node.getGenericSpecialization(), true, false); 1424 addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
1423 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); 1425 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
1440 1442
1441 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); 1443 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
1442 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true); 1444 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true);
1443 builder.end().end(); 1445 builder.end().end();
1444 1446
1447 final String currentNodeVar = currentNode;
1448 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock<SpecializationData>() {
1449
1450 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
1451 return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar);
1452 }
1453 }));
1454
1455 boolean firstUnreachable = true;
1456 for (SpecializationData current : node.getSpecializations()) {
1457 if (current.isUninitialized() || current.isReachable()) {
1458 continue;
1459 }
1460 if (firstUnreachable) {
1461 emitEncounteredSynthetic(builder, current);
1462 firstUnreachable = false;
1463 }
1464 }
1465 emitUnreachableSpecializations(builder, node);
1466
1467 return method;
1468 }
1469
1470 private SpecializationGroup createSpecializationGroups(final NodeData node) {
1445 List<SpecializationData> specializations = node.getSpecializations(); 1471 List<SpecializationData> specializations = node.getSpecializations();
1446 List<SpecializationData> filteredSpecializations = new ArrayList<>(); 1472 List<SpecializationData> filteredSpecializations = new ArrayList<>();
1447 for (SpecializationData current : specializations) { 1473 for (SpecializationData current : specializations) {
1448 if (current.isUninitialized() || !current.isReachable()) { 1474 if (current.isUninitialized() || !current.isReachable()) {
1449 continue; 1475 continue;
1450 } 1476 }
1451 filteredSpecializations.add(current); 1477 filteredSpecializations.add(current);
1452 } 1478 }
1453 1479
1454 List<SpecializationGroup> groups = SpecializationGroup.create(filteredSpecializations); 1480 return SpecializationGroup.create(filteredSpecializations);
1455 1481 }
1456 final String currentNodeVar = currentNode; 1482
1457 for (SpecializationGroup group : groups) { 1483 private CodeExecutableElement createGenericExecute(NodeData node, SpecializationGroup group) {
1458 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, true, new CodeBlock<SpecializationData>() { 1484 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1459 1485 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME);
1460 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { 1486
1461 return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar); 1487 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
1462 } 1488
1463 })); 1489 addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(), false);
1464 } 1490 final CodeTreeBuilder builder = method.createBuilder();
1465 1491
1466 boolean firstUnreachable = true; 1492 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock<SpecializationData>() {
1467 for (SpecializationData current : specializations) { 1493
1494 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
1495 return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current);
1496 }
1497 }));
1498
1499 emitUnreachableSpecializations(builder, node);
1500
1501 return method;
1502 }
1503
1504 private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) {
1505 for (SpecializationData current : node.getSpecializations()) {
1468 if (current.isUninitialized() || current.isReachable()) { 1506 if (current.isUninitialized() || current.isReachable()) {
1469 continue; 1507 continue;
1470 } 1508 }
1471 if (firstUnreachable) {
1472 emitEncounteredSynthetic(builder, current);
1473 firstUnreachable = false;
1474 }
1475
1476 builder.string("// unreachable ").string(current.getId()).newLine(); 1509 builder.string("// unreachable ").string(current.getId()).newLine();
1477 } 1510 }
1478
1479 return method;
1480 }
1481
1482 private CodeExecutableElement createGenericExecute(NodeData node) {
1483 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1484 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME);
1485
1486 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
1487
1488 addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(), false);
1489 final CodeTreeBuilder builder = method.createBuilder();
1490
1491 List<SpecializationData> specializations = node.getSpecializations();
1492 List<SpecializationData> filteredSpecializations = new ArrayList<>();
1493 for (SpecializationData current : specializations) {
1494 if (current.isUninitialized() || !current.isReachable()) {
1495 continue;
1496 }
1497 filteredSpecializations.add(current);
1498 }
1499
1500 List<SpecializationGroup> groups = SpecializationGroup.create(filteredSpecializations);
1501
1502 for (SpecializationGroup group : groups) {
1503 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock<SpecializationData>() {
1504
1505 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
1506 return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current);
1507 }
1508 }));
1509 }
1510
1511 for (SpecializationData current : specializations) {
1512 if (current.isUninitialized() || current.isReachable()) {
1513 continue;
1514 }
1515 builder.string("// unreachable ").string(current.getId()).newLine();
1516 }
1517
1518 return method;
1519 } 1511 }
1520 1512
1521 private CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, 1513 private CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState,
1522 final CodeBlock<SpecializationData> guardedblock) { 1514 final CodeBlock<SpecializationData> guardedblock) {
1523 return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Void>() { 1515 return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Void>() {
1539 } 1531 }
1540 }); 1532 });
1541 } 1533 }
1542 1534
1543 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Void> bodyBlock) { 1535 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Void> bodyBlock) {
1536 CodeTreeBuilder builder = parent.create();
1537
1538 int ifCount = emitGuards(builder, source, group, checkMinimumState);
1539
1540 if (isReachableGroup(group, ifCount, checkMinimumState)) {
1541 builder.tree(bodyBlock.create(builder, null));
1542 }
1543
1544 builder.end(ifCount);
1545
1546 return builder.getRoot();
1547 }
1548
1549 private boolean isReachableGroup(SpecializationGroup group, int ifCount, boolean checkMinimumState) {
1550 if (ifCount != 0) {
1551 return true;
1552 }
1553 SpecializationGroup previous = group.getPreviousGroup();
1554 if (previous == null || previous.getElseConnectableGuard() == null) {
1555 return true;
1556 }
1557
1558 /*
1559 * Hacky else case. In this case the specialization is not reachable due to previous
1560 * else branch. This is only true if the minimum state is not checked.
1561 */
1562 if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && !checkMinimumState &&
1563 (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
1564 return false;
1565 }
1566
1567 return true;
1568 }
1569
1570 private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState) {
1544 NodeData node = source.getNode(); 1571 NodeData node = source.getNode();
1545 1572
1546 CodeTreeBuilder guardsBuilder = parent.create(); 1573 CodeTreeBuilder guardsBuilder = builder.create();
1547 CodeTreeBuilder castBuilder = parent.create(); 1574 CodeTreeBuilder castBuilder = builder.create();
1548 CodeTreeBuilder guardsCastBuilder = parent.create(); 1575 CodeTreeBuilder guardsCastBuilder = builder.create();
1549 1576
1550 String guardsAnd = ""; 1577 String guardsAnd = "";
1551 String guardsCastAnd = ""; 1578 String guardsCastAnd = "";
1579
1580 GuardData elseGuard = group.getElseConnectableGuard();
1552 1581
1553 boolean minimumState = checkMinimumState; 1582 boolean minimumState = checkMinimumState;
1554 if (minimumState) { 1583 if (minimumState) {
1555 int groupMaxIndex = group.getMaxSpecializationIndex(); 1584 int groupMaxIndex = group.getMaxSpecializationIndex();
1556 1585
1583 guardsBuilder.string("this"); 1612 guardsBuilder.string("this");
1584 guardsBuilder.string(".").string(assumption).string(".isValid()"); 1613 guardsBuilder.string(".").string(assumption).string(".isValid()");
1585 guardsAnd = " && "; 1614 guardsAnd = " && ";
1586 } 1615 }
1587 1616
1588 int argOffset = group.getTypeGuardOffset(); 1617 for (TypeGuard typeGuard : group.getTypeGuards()) {
1589 int argIndex = argOffset; 1618 ActualParameter valueParam = source.getSignatureParameter(typeGuard.getSignatureIndex());
1590 for (TypeData typeData : group.getTypeGuards()) {
1591
1592 ActualParameter valueParam = source.getSignatureParameter(argIndex);
1593 1619
1594 if (valueParam == null) { 1620 if (valueParam == null) {
1595 /* 1621 /*
1596 * If used inside a execute evaluated method then the value param may not exist. 1622 * If used inside a execute evaluated method then the value param may not exist.
1597 * In that case we assume that the value is executed generic or of the current 1623 * In that case we assume that the value is executed generic or of the current
1598 * specialization. 1624 * specialization.
1599 */ 1625 */
1600 if (group.getSpecialization() != null) { 1626 if (group.getSpecialization() != null) {
1601 valueParam = group.getSpecialization().getSignatureParameter(argIndex); 1627 valueParam = group.getSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
1602 } else { 1628 } else {
1603 valueParam = node.getGenericSpecialization().getSignatureParameter(argIndex); 1629 valueParam = node.getGenericSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
1604 } 1630 }
1605 } 1631 }
1606 1632
1607 NodeChildData child = node.findChild(valueParam.getSpecification().getName()); 1633 NodeChildData child = node.findChild(valueParam.getSpecification().getName());
1608 if (child == null) { 1634 if (child == null) {
1609 throw new IllegalStateException(); 1635 throw new IllegalStateException();
1610 } 1636 }
1611 1637
1612 CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeData); 1638 CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeGuard.getType());
1613 if (implicitGuard != null) { 1639 if (implicitGuard != null) {
1614 guardsBuilder.string(guardsAnd); 1640 guardsBuilder.string(guardsAnd);
1615 guardsBuilder.tree(implicitGuard); 1641 guardsBuilder.tree(implicitGuard);
1616 guardsAnd = " && "; 1642 guardsAnd = " && ";
1617 } 1643 }
1618 1644
1619 CodeTree cast = createCast(castBuilder, child, valueParam, typeData); 1645 CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType());
1620 if (cast != null) { 1646 if (cast != null) {
1621 castBuilder.tree(cast); 1647 castBuilder.tree(cast);
1622 } 1648 }
1623 1649 }
1624 argIndex++; 1650
1625 } 1651 for (GuardData guard : group.getGuards()) {
1626 CodeTreeBuilder builder = parent.create(); 1652 if (elseGuard == guard) {
1627 1653 continue;
1628 int ifCount = 0; 1654 }
1629 if (isElseConnectableGroup(group)) { 1655
1630 if (minimumState) { 1656 if (needsTypeGuard(source, group, guard)) {
1631 builder.startElseIf().tree(guardsBuilder.getRoot()).end().startBlock(); 1657 guardsCastBuilder.tree(createMethodGuard(builder, guardsCastAnd, source, guard));
1658 guardsCastAnd = " && ";
1632 } else { 1659 } else {
1633 builder.startElseBlock(); 1660 guardsBuilder.tree(createMethodGuard(builder, guardsAnd, source, guard));
1634 } 1661 guardsAnd = " && ";
1635 ifCount++; 1662 }
1636 1663 }
1637 } else { 1664
1638 for (GuardData guard : group.getGuards()) { 1665 int ifCount = startGuardIf(builder, guardsBuilder, 0, elseGuard);
1639 if (needsTypeGuard(source, group, guard)) { 1666 builder.tree(castBuilder.getRoot());
1640 guardsCastBuilder.tree(createMethodGuard(parent, guardsCastAnd, source, guard)); 1667 ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuard);
1641 guardsCastAnd = " && "; 1668 return ifCount;
1642 } else { 1669 }
1643 guardsBuilder.tree(createMethodGuard(parent, guardsAnd, source, guard)); 1670
1644 guardsAnd = " && "; 1671 private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, GuardData elseGuard) {
1645 } 1672 int newIfCount = ifCount;
1646 } 1673
1647 1674 if (!conditionBuilder.isEmpty()) {
1648 if (!guardsBuilder.isEmpty()) { 1675 if (ifCount == 0 && elseGuard != null) {
1649 builder.startIf().tree(guardsBuilder.getRoot()).end().startBlock(); 1676 builder.startElseIf();
1650 ifCount++; 1677 } else {
1651 } 1678 builder.startIf();
1652 builder.tree(castBuilder.getRoot()); 1679 }
1653 1680 builder.tree(conditionBuilder.getRoot());
1654 if (!guardsCastBuilder.isEmpty()) { 1681 builder.end().startBlock();
1655 builder.startIf().tree(guardsCastBuilder.getRoot()).end().startBlock(); 1682 newIfCount++;
1656 ifCount++; 1683 } else if (ifCount == 0 && elseGuard != null) {
1657 } 1684 builder.startElseBlock();
1658 } 1685 newIfCount++;
1659 1686 }
1660 builder.tree(bodyBlock.create(builder, null)); 1687 return newIfCount;
1661
1662 builder.end(ifCount);
1663 return builder.getRoot();
1664 }
1665
1666 private boolean isElseConnectableGroup(SpecializationGroup group) {
1667 if (!group.getTypeGuards().isEmpty() || !group.getAssumptions().isEmpty()) {
1668 return false;
1669 }
1670
1671 SpecializationGroup previousGroup = group.getPreviousGroup();
1672 if (previousGroup != null && group.getGuards().size() == 1 && previousGroup.getGuards().size() == 1) {
1673 GuardData guard = group.getGuards().get(0);
1674 GuardData previousGuard = previousGroup.getGuards().get(0);
1675
1676 if (guard.getMethod().equals(previousGuard.getMethod())) {
1677 assert guard.isNegated() != previousGuard.isNegated();
1678 return true;
1679 }
1680 }
1681 return false;
1682 } 1688 }
1683 1689
1684 private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardData guard) { 1690 private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardData guard) {
1685 int offset = group.getTypeGuardOffset(); 1691 int signatureIndex = 0;
1686 int argIndex = 0;
1687 for (ActualParameter parameter : guard.getParameters()) { 1692 for (ActualParameter parameter : guard.getParameters()) {
1688 if (!parameter.getSpecification().isSignature()) { 1693 if (!parameter.getSpecification().isSignature()) {
1689 continue; 1694 continue;
1690 } 1695 }
1691 if (argIndex < offset) { 1696
1692 // type casted in parent group 1697 TypeGuard typeGuard = group.findTypeGuard(signatureIndex);
1693 continue; 1698 if (typeGuard != null) {
1694 } 1699 TypeData requiredType = typeGuard.getType();
1695
1696 int guardIndex = argIndex - offset;
1697 if (guardIndex < group.getTypeGuards().size()) {
1698 TypeData requiredType = group.getTypeGuards().get(guardIndex);
1699 1700
1700 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); 1701 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
1701 if (sourceParameter == null) { 1702 if (sourceParameter == null) {
1702 sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); 1703 sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
1703 } 1704 }
1704 1705
1705 if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), requiredType)) { 1706 if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), requiredType)) {
1706 return true; 1707 return true;
1707 } 1708 }
1708 } 1709 }
1709 argIndex++; 1710
1711 signatureIndex++;
1710 } 1712 }
1711 return false; 1713 return false;
1712 } 1714 }
1713 1715
1714 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) { 1716 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) {
1747 builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar)); 1749 builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar));
1748 builder.end(); 1750 builder.end();
1749 } else { 1751 } else {
1750 // simple rewrite 1752 // simple rewrite
1751 if (current.getExceptions().isEmpty()) { 1753 if (current.getExceptions().isEmpty()) {
1752 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null))); 1754 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null), null));
1753 } else { 1755 } else {
1754 builder.startStatement().string(currentNodeVar).string(" = ").tree(createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null)).end(); 1756 builder.startStatement().string(currentNodeVar).string(" = ").tree(createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null)).end();
1755 builder.tree(createGenericInvoke(builder, source, current, CodeTreeBuilder.singleString(currentNodeVar))); 1757 builder.tree(createGenericInvoke(builder, source, current, null, CodeTreeBuilder.singleString(currentNodeVar)));
1756 } 1758 }
1757 } 1759 }
1758 CodeTreeBuilder root = parent.create(); 1760 CodeTreeBuilder root = parent.create();
1759 root.tree(prefix.getRoot()); 1761 root.tree(prefix.getRoot());
1760 root.tree(encloseThrowsWithFallThrough(current, builder.getRoot())); 1762 root.tree(encloseThrowsWithFallThrough(current, builder.getRoot()));
1768 builder.declaration(getContext().getTruffleTypes().getNode(), "root", currentNode); 1770 builder.declaration(getContext().getTruffleTypes().getNode(), "root", currentNode);
1769 builder.startIf().string(currentNode).string(".next0 != null").end().startBlock(); 1771 builder.startIf().string(currentNode).string(".next0 != null").end().startBlock();
1770 builder.tree(createFindRoot(builder, node, false)); 1772 builder.tree(createFindRoot(builder, node, false));
1771 builder.end(); 1773 builder.end();
1772 builder.end(); 1774 builder.end();
1773 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, "root", currentNode, null))); 1775 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, "root", "(" + baseClassName(node) + ") root", null), null));
1774 return builder.getRoot(); 1776 return builder.getRoot();
1775 } 1777 }
1776 1778
1777 protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) { 1779 protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) {
1778 CodeTreeBuilder builder = parent.create(); 1780 CodeTreeBuilder builder = parent.create();
1804 builder.end(); 1806 builder.end();
1805 1807
1806 return builder.getRoot(); 1808 return builder.getRoot();
1807 } 1809 }
1808 1810
1809 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, CodeTree replaceCall) { 1811 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, CodeTree replaceCall, CodeTree replaceVar) {
1812 assert replaceCall == null || replaceVar == null;
1810 CodeTreeBuilder builder = parent.create(); 1813 CodeTreeBuilder builder = parent.create();
1814 CodeTree replace = replaceVar;
1815 if (replace == null) {
1816 replace = replaceCall;
1817 }
1811 if (current.isGeneric()) { 1818 if (current.isGeneric()) {
1812 builder.startReturn().tree(replaceCall).string(".").startCall(EXECUTE_GENERIC_NAME); 1819 builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME);
1813 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true); 1820 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true);
1814 builder.end().end(); 1821 builder.end().end();
1815
1816 } else if (current.getMethod() == null) { 1822 } else if (current.getMethod() == null) {
1817 builder.statement(replaceCall); 1823 if (replaceCall != null) {
1824 builder.statement(replaceCall);
1825 }
1818 emitEncounteredSynthetic(builder, current); 1826 emitEncounteredSynthetic(builder, current);
1819 } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) { 1827 } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) {
1820 builder.statement(replaceCall); 1828 if (replaceCall != null) {
1829 builder.statement(replaceCall);
1830 }
1821 builder.startReturn().tree(createTemplateMethodCall(parent, null, source, current, null)).end(); 1831 builder.startReturn().tree(createTemplateMethodCall(parent, null, source, current, null)).end();
1822 } else { 1832 } else {
1823 replaceCall.add(new CodeTree(CodeTreeKind.STRING, null, ".")); 1833 replace.add(new CodeTree(CodeTreeKind.STRING, null, "."));
1824 builder.startReturn().tree(createTemplateMethodCall(parent, replaceCall, source, current, null)).end(); 1834 builder.startReturn().tree(createTemplateMethodCall(parent, replace, source, current, null)).end();
1825 } 1835 }
1826 return builder.getRoot(); 1836 return builder.getRoot();
1827 } 1837 }
1828 1838
1829 protected CodeTree createReplaceCall(CodeTreeBuilder builder, SpecializationData current, String target, String source, String message) { 1839 protected CodeTree createReplaceCall(CodeTreeBuilder builder, SpecializationData current, String target, String source, String message) {
2492 2502
2493 builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end(); 2503 builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end();
2494 builder.startBlock(); 2504 builder.startBlock();
2495 String message = ("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"); 2505 String message = ("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")");
2496 builder.tree(createGenericInvoke(builder, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization(), 2506 builder.tree(createGenericInvoke(builder, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization(),
2497 createReplaceCall(builder, node.getGenericSpecialization(), "root", "this", message))); 2507 createReplaceCall(builder, node.getGenericSpecialization(), "root", "this", message), null));
2498 builder.end(); 2508 builder.end();
2499 2509
2500 builder.startElseBlock(); 2510 builder.startElseBlock();
2501 builder.startStatement().startCall("setNext0"); 2511 builder.startStatement().startCall("setNext0");
2502 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); 2512 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();