comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 11195:4f52b08bd2f9

Truffle-DSL: Implemented specialization grouping for generic cases.
author Christian Humer <christian.humer@gmail.com>
date Thu, 01 Aug 2013 20:53:54 +0200
parents 4eb23800c907
children 3479ab380552
comparison
equal deleted inserted replaced
11194:14d5ff4683e0 11195:4f52b08bd2f9
438 438
439 if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) { 439 if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) {
440 continue; 440 continue;
441 } 441 }
442 442
443 CodeTree cast = createCast(parent, field, valueParam, guardedParam); 443 CodeTree cast = createCast(parent, field, valueParam, guardedParam.getTypeSystemType());
444 if (cast == null) { 444 if (cast == null) {
445 continue; 445 continue;
446 } 446 }
447 builder.tree(cast); 447 builder.tree(cast);
448 } 448 }
477 * case it assumes that the value is already converted. 477 * case it assumes that the value is already converted.
478 */ 478 */
479 valueParam = guardedParam; 479 valueParam = guardedParam;
480 } 480 }
481 481
482 CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); 482 CodeTree implicitGuard = createTypeGuard(builder, field, valueParam, guardedParam.getTypeSystemType());
483 if (implicitGuard == null) { 483 if (implicitGuard == null) {
484 continue; 484 continue;
485 } 485 }
486 486
487 builder.string(andOperator); 487 builder.string(andOperator);
490 } 490 }
491 491
492 return builder.isEmpty() ? null : builder.getRoot(); 492 return builder.isEmpty() ? null : builder.getRoot();
493 } 493 }
494 494
495 private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { 495 private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) {
496 NodeData node = field.getNodeData(); 496 NodeData node = field.getNodeData();
497
497 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 498 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
498 499
499 TypeData targetType = target.getTypeSystemType();
500 TypeData sourceType = source.getTypeSystemType(); 500 TypeData sourceType = source.getTypeSystemType();
501 501
502 if (!sourceType.needsCastTo(getContext(), targetType)) { 502 if (!sourceType.needsCastTo(getContext(), targetType)) {
503 return null; 503 return null;
504 } 504 }
505 505
506 builder.startGroup(); 506 builder.startGroup();
507 507
508 if (field.isShortCircuit()) { 508 if (field.isShortCircuit()) {
509 ActualParameter shortCircuit = target.getPreviousParameter(); 509 ActualParameter shortCircuit = source.getPreviousParameter();
510 assert shortCircuit != null; 510 assert shortCircuit != null;
511 builder.string("("); 511 builder.string("(");
512 builder.string("!").string(valueName(shortCircuit)); 512 builder.string("!").string(valueName(shortCircuit));
513 builder.string(" || "); 513 builder.string(" || ");
514 } 514 }
515 515
516 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getTypeSystemType())); 516 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(targetType));
517 builder.string(valueName(source)); 517 builder.string(valueName(source));
518 builder.end().end(); // call 518 builder.end().end(); // call
519 519
520 if (field.isShortCircuit()) { 520 if (field.isShortCircuit()) {
521 builder.string(")"); 521 builder.string(")");
524 builder.end(); // group 524 builder.end(); // group
525 525
526 return builder.getRoot(); 526 return builder.getRoot();
527 } 527 }
528 528
529 private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { 529 private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) {
530 NodeData node = field.getNodeData(); 530 NodeData node = field.getNodeData();
531 TypeData sourceType = source.getTypeSystemType(); 531 TypeData sourceType = source.getTypeSystemType();
532 TypeData targetType = target.getTypeSystemType();
533 532
534 if (!sourceType.needsCastTo(getContext(), targetType)) { 533 if (!sourceType.needsCastTo(getContext(), targetType)) {
535 return null; 534 return null;
536 } 535 }
537 536
538 CodeTree condition = null; 537 CodeTree condition = null;
539 if (field.isShortCircuit()) { 538 if (field.isShortCircuit()) {
540 ActualParameter shortCircuit = target.getPreviousParameter(); 539 ActualParameter shortCircuit = source.getPreviousParameter();
541 assert shortCircuit != null; 540 assert shortCircuit != null;
542 condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); 541 condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
543 } 542 }
544 543
545 CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(target))); 544 CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(source)));
546 545
547 return createLazyAssignment(parent, castValueName(target), target.getType(), condition, value); 546 return createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value);
548 } 547 }
549 548
550 /** 549 /**
551 * <pre> 550 * <pre>
552 * variant1 $condition != null 551 * variant1 $condition != null
1414 1413
1415 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); 1414 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
1416 return var; 1415 return var;
1417 } 1416 }
1418 1417
1419 private CodeExecutableElement createGenericExecuteAndSpecialize(NodeData node) { 1418 private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node) {
1420
1421 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); 1419 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1422 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME); 1420 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME);
1423 method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState")); 1421 method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState"));
1424 addInternalValueParameters(method, node.getGenericSpecialization(), true, false); 1422 addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
1425 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); 1423 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
1434 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); 1432 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
1435 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true); 1433 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true);
1436 builder.end().end(); 1434 builder.end().end();
1437 1435
1438 List<SpecializationData> specializations = node.getSpecializations(); 1436 List<SpecializationData> specializations = node.getSpecializations();
1437 List<SpecializationData> filteredSpecializations = new ArrayList<>();
1438 for (SpecializationData current : specializations) {
1439 if (current.isUninitialized() || !current.isReachable()) {
1440 continue;
1441 }
1442 filteredSpecializations.add(current);
1443 }
1444
1445 List<SpecializationGroup> groups = SpecializationGroup.create(filteredSpecializations);
1446
1447 for (SpecializationGroup group : groups) {
1448 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, true, new CodeBlock<SpecializationData>() {
1449
1450 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
1451 return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current);
1452 }
1453 }));
1454 }
1439 1455
1440 boolean firstUnreachable = true; 1456 boolean firstUnreachable = true;
1441 SpecializationData previous = null;
1442 for (SpecializationData current : specializations) { 1457 for (SpecializationData current : specializations) {
1443 if (current.isUninitialized()) { 1458 if (current.isUninitialized() || current.isReachable()) {
1444 continue; 1459 continue;
1445 } 1460 }
1446 String prefix = null; 1461 if (firstUnreachable) {
1447 1462 emitEncounteredSynthetic(builder, current);
1448 if (current.hasRewrite(getContext())) { 1463 firstUnreachable = false;
1449 prefix = "minimumState < " + node.getSpecializations().indexOf(current); 1464 }
1450 } 1465
1451 1466 builder.string("// unreachable ").string(current.getId()).newLine();
1452 if (current.isReachable()) {
1453 CodeTree execute = createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current);
1454
1455 builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute, null, true, false));
1456 } else {
1457 if (firstUnreachable) {
1458 if (previous != null && !previous.isGenericSpecialization(getContext()) && !previous.hasRewrite(getContext())) {
1459 emitEncounteredSynthetic(builder, current);
1460 }
1461 firstUnreachable = false;
1462 }
1463 builder.string("// unreachable ").string(current.getId()).newLine();
1464 }
1465 previous = current;
1466 } 1467 }
1467 1468
1468 return method; 1469 return method;
1469 } 1470 }
1470 1471
1473 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME); 1474 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME);
1474 1475
1475 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath())); 1476 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
1476 1477
1477 addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(), false); 1478 addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(), false);
1478 CodeTreeBuilder builder = method.createBuilder(); 1479 final CodeTreeBuilder builder = method.createBuilder();
1479 1480
1480 String prefix = null;
1481 List<SpecializationData> specializations = node.getSpecializations(); 1481 List<SpecializationData> specializations = node.getSpecializations();
1482 1482 List<SpecializationData> filteredSpecializations = new ArrayList<>();
1483 for (SpecializationData current : specializations) { 1483 for (SpecializationData current : specializations) {
1484 if (current.isUninitialized() || !current.isReachable()) { 1484 if (current.isUninitialized() || !current.isReachable()) {
1485 continue; 1485 continue;
1486 } 1486 }
1487 CodeTreeBuilder execute = new CodeTreeBuilder(builder); 1487 filteredSpecializations.add(current);
1488 execute.tree(createGenericInvoke(builder, node.getGenericSpecialization(), current)); 1488 }
1489 builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false)); 1489
1490 List<SpecializationGroup> groups = SpecializationGroup.create(filteredSpecializations);
1491
1492 for (SpecializationGroup group : groups) {
1493 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock<SpecializationData>() {
1494
1495 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
1496 return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current);
1497 }
1498 }));
1490 } 1499 }
1491 1500
1492 for (SpecializationData current : specializations) { 1501 for (SpecializationData current : specializations) {
1493 if (current.isUninitialized() || current.isReachable()) { 1502 if (current.isUninitialized() || current.isReachable()) {
1494 continue; 1503 continue;
1495 } 1504 }
1496 builder.string("// unreachable ").string(current.getId()).newLine(); 1505 builder.string("// unreachable ").string(current.getId()).newLine();
1497 } 1506 }
1498 1507
1499 return method; 1508 return method;
1509 }
1510
1511 private CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState,
1512 final CodeBlock<SpecializationData> guardedblock) {
1513 return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Void>() {
1514
1515 public CodeTree create(CodeTreeBuilder parent, Void value) {
1516 CodeTreeBuilder builder = parent.create();
1517
1518 if (group.getSpecialization() != null) {
1519 builder.tree(guardedblock.create(builder, group.getSpecialization()));
1520
1521 assert group.getChildren().isEmpty() : "missed a specialization";
1522 } else {
1523 for (SpecializationGroup childGroup : group.getChildren()) {
1524 builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock));
1525 }
1526 }
1527
1528 return builder.getRoot();
1529 }
1530 });
1531 }
1532
1533 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Void> bodyBlock) {
1534 NodeData node = source.getNode();
1535
1536 CodeTreeBuilder guardsBuilder = parent.create();
1537 CodeTreeBuilder castBuilder = parent.create();
1538 CodeTreeBuilder guardsCastBuilder = parent.create();
1539
1540 String guardsAnd = "";
1541 String guardsCastAnd = "";
1542
1543 boolean minimumState = checkMinimumState;
1544 if (minimumState) {
1545 int groupMaxIndex = group.getMaxSpecializationIndex();
1546
1547 int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization());
1548 if (groupMaxIndex >= genericIndex) {
1549 // no minimum state check for an generic index
1550 minimumState = false;
1551 }
1552
1553 if (minimumState) {
1554 // no minimum state check if alread checked by parent group
1555 int parentMaxIndex = -1;
1556 if (group.getParent() != null) {
1557 parentMaxIndex = group.getParent().getMaxSpecializationIndex();
1558 }
1559 if (groupMaxIndex == parentMaxIndex) {
1560 minimumState = false;
1561 }
1562 }
1563
1564 if (minimumState) {
1565 guardsBuilder.string(guardsAnd);
1566 guardsBuilder.string("minimumState < " + groupMaxIndex);
1567 guardsAnd = " && ";
1568 }
1569 }
1570
1571 for (String assumption : group.getAssumptions()) {
1572 guardsBuilder.string(guardsAnd);
1573 guardsBuilder.string("this");
1574 guardsBuilder.string(".").string(assumption).string(".isValid()");
1575 guardsAnd = " && ";
1576 }
1577
1578 int argOffset = group.getTypeGuardOffset();
1579 int argIndex = argOffset;
1580 for (TypeData typeData : group.getTypeGuards()) {
1581
1582 ActualParameter valueParam = source.getSignatureParameter(argIndex);
1583
1584 if (valueParam == null) {
1585 /*
1586 * If used inside a execute evaluated method then the value param may not exist.
1587 * In that case we assume that the value is executed generic or of the current
1588 * specialization.
1589 */
1590 if (group.getSpecialization() != null) {
1591 valueParam = group.getSpecialization().getSignatureParameter(argIndex);
1592 } else {
1593 valueParam = node.getGenericSpecialization().getSignatureParameter(argIndex);
1594 }
1595 }
1596
1597 NodeChildData child = node.findChild(valueParam.getSpecification().getName());
1598 if (child == null) {
1599 throw new IllegalStateException();
1600 }
1601
1602 CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeData);
1603 if (implicitGuard != null) {
1604 guardsBuilder.string(guardsAnd);
1605 guardsBuilder.tree(implicitGuard);
1606 guardsAnd = " && ";
1607 }
1608
1609 CodeTree cast = createCast(castBuilder, child, valueParam, typeData);
1610 if (cast != null) {
1611 castBuilder.tree(cast);
1612 }
1613
1614 argIndex++;
1615 }
1616 CodeTreeBuilder builder = parent.create();
1617
1618 int ifCount = 0;
1619 if (isElseConnectableGroup(group)) {
1620 if (minimumState) {
1621 builder.startElseIf().tree(guardsBuilder.getRoot()).end().startBlock();
1622 } else {
1623 builder.startElseBlock();
1624 }
1625 ifCount++;
1626
1627 } else {
1628 for (GuardData guard : group.getGuards()) {
1629 if (needsTypeGuard(source, group, guard)) {
1630 guardsCastBuilder.tree(createMethodGuard(parent, guardsCastAnd, source, guard));
1631 guardsCastAnd = " && ";
1632 } else {
1633 guardsBuilder.tree(createMethodGuard(parent, guardsAnd, source, guard));
1634 guardsAnd = " && ";
1635 }
1636 }
1637
1638 if (!guardsBuilder.isEmpty()) {
1639 builder.startIf().tree(guardsBuilder.getRoot()).end().startBlock();
1640 ifCount++;
1641 }
1642 builder.tree(castBuilder.getRoot());
1643
1644 if (!guardsCastBuilder.isEmpty()) {
1645 builder.startIf().tree(guardsCastBuilder.getRoot()).end().startBlock();
1646 ifCount++;
1647 }
1648 }
1649
1650 builder.tree(bodyBlock.create(builder, null));
1651
1652 builder.end(ifCount);
1653 return builder.getRoot();
1654 }
1655
1656 private boolean isElseConnectableGroup(SpecializationGroup group) {
1657 if (!group.getTypeGuards().isEmpty() || !group.getAssumptions().isEmpty()) {
1658 return false;
1659 }
1660
1661 SpecializationGroup previousGroup = group.getPreviousGroup();
1662 if (previousGroup != null && group.getGuards().size() == 1 && previousGroup.getGuards().size() == 1) {
1663 GuardData guard = group.getGuards().get(0);
1664 GuardData previousGuard = previousGroup.getGuards().get(0);
1665
1666 if (guard.getMethod().equals(previousGuard.getMethod())) {
1667 assert guard.isNegated() != previousGuard.isNegated();
1668 return true;
1669 }
1670 }
1671 return false;
1672 }
1673
1674 private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardData guard) {
1675 int offset = group.getTypeGuardOffset();
1676 int argIndex = 0;
1677 for (ActualParameter parameter : guard.getParameters()) {
1678 if (!parameter.getSpecification().isSignature()) {
1679 continue;
1680 }
1681 if (argIndex < offset) {
1682 // type casted in parent group
1683 continue;
1684 }
1685
1686 int guardIndex = argIndex - offset;
1687 if (guardIndex < group.getTypeGuards().size()) {
1688 TypeData requiredType = group.getTypeGuards().get(guardIndex);
1689
1690 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
1691 if (sourceParameter == null) {
1692 sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
1693 }
1694
1695 if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), requiredType)) {
1696 return true;
1697 }
1698 }
1699 argIndex++;
1700 }
1701 return false;
1702 }
1703
1704 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) {
1705 CodeTreeBuilder builder = parent.create();
1706 builder.string(prefix);
1707 if (guard.isNegated()) {
1708 builder.string("!");
1709 }
1710 builder.tree(createTemplateMethodCall(builder, null, source, guard, null));
1711 return builder.getRoot();
1500 } 1712 }
1501 1713
1502 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { 1714 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
1503 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1715 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1504 1716
1506 emitEncounteredSynthetic(builder, current); 1718 emitEncounteredSynthetic(builder, current);
1507 } else { 1719 } else {
1508 builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end(); 1720 builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
1509 } 1721 }
1510 1722
1511 return encloseThrowsWithFallThrough(current, builder.getRoot()); 1723 return encloseThrowsWithFallThrough(current, builder.getRoot(), null);
1512 } 1724 }
1513 1725
1514 protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { 1726 protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
1515 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1727 CodeTreeBuilder builder = parent.create();
1728 CodeTreeBuilder prefix = parent.create();
1516 1729
1517 NodeData node = current.getNode(); 1730 NodeData node = current.getNode();
1518 1731
1732 String restoreNode = null;
1519 if (current.isGeneric() && node.isPolymorphic()) { 1733 if (current.isGeneric() && node.isPolymorphic()) {
1520 builder.startIf().string("next0 == null && minimumState > 0").end().startBlock(); 1734 builder.startIf().string("next0 == null && minimumState > 0").end().startBlock();
1521 builder.tree(createRewritePolymorphic(builder, node)); 1735 builder.tree(createRewritePolymorphic(builder, node));
1522 builder.end(); 1736 builder.end();
1523 builder.startElseBlock(); 1737 builder.startElseBlock();
1524 builder.tree(createRewriteGeneric(builder, source, current)); 1738 builder.tree(createRewriteGeneric(builder, source, current));
1525 builder.end(); 1739 builder.end();
1526 } else { 1740 } else {
1527 // simple rewrite 1741 // simple rewrite
1528 builder.tree(createReturnRewriteAndInvoke(builder, null, null, source, current)); 1742 if (current.getExceptions().isEmpty()) {
1529 } 1743 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, null, null)));
1530 1744 } else {
1531 return encloseThrowsWithFallThrough(current, builder.getRoot()); 1745 prefix.declaration(baseClassName(node), "restoreNode", createReplaceCall(builder, current, null, null));
1746 builder.tree(createGenericInvoke(builder, source, current, CodeTreeBuilder.singleString("restoreNode")));
1747 restoreNode = "restoreNode";
1748 }
1749 }
1750 CodeTreeBuilder root = parent.create();
1751 root.tree(prefix.getRoot());
1752 root.tree(encloseThrowsWithFallThrough(current, builder.getRoot(), restoreNode));
1753 return root.getRoot();
1532 } 1754 }
1533 1755
1534 private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { 1756 private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
1535 NodeData node = current.getNode(); 1757 NodeData node = current.getNode();
1536 1758
1538 builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this"); 1760 builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this");
1539 builder.startIf().string("next0 != null").end().startBlock(); 1761 builder.startIf().string("next0 != null").end().startBlock();
1540 builder.tree(createFindRoot(builder, node, false)); 1762 builder.tree(createFindRoot(builder, node, false));
1541 builder.end(); 1763 builder.end();
1542 builder.end(); 1764 builder.end();
1543 builder.tree(createReturnRewriteAndInvoke(builder, "root", null, source, current)); 1765 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, "root", null)));
1544 return builder.getRoot(); 1766 return builder.getRoot();
1545 } 1767 }
1546 1768
1547 protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) { 1769 protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) {
1548 CodeTreeBuilder builder = parent.create(); 1770 CodeTreeBuilder builder = parent.create();
1557 builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end(); 1779 builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end();
1558 builder.end(); 1780 builder.end();
1559 return builder.getRoot(); 1781 return builder.getRoot();
1560 } 1782 }
1561 1783
1562 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { 1784 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree, String restoreNodeVarName) {
1563 if (current.getExceptions().isEmpty()) { 1785 if (current.getExceptions().isEmpty()) {
1564 return tree; 1786 return tree;
1565 } 1787 }
1566 CodeTreeBuilder builder = new CodeTreeBuilder(null); 1788 CodeTreeBuilder builder = new CodeTreeBuilder(null);
1567 1789
1568 builder.startTryBlock(); 1790 builder.startTryBlock();
1569 builder.tree(tree); 1791 builder.tree(tree);
1570 for (SpecializationThrowsData exception : current.getExceptions()) { 1792 for (SpecializationThrowsData exception : current.getExceptions()) {
1571 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); 1793 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
1794 if (restoreNodeVarName != null) {
1795 builder.startStatement().startCall(restoreNodeVarName, "replace").string("this");
1796 builder.startGroup();
1797 builder.startCall("createInfo0").doubleQuote("Rewrite exception thrown " + Utils.getSimpleName(exception.getJavaClass()) + ".");
1798 addInternalValueParameterNames(builder, current, current, null, false, true);
1799 builder.end();
1800 builder.end();
1801 builder.end().end();
1802 }
1803
1572 builder.string("// fall through").newLine(); 1804 builder.string("// fall through").newLine();
1573 } 1805 }
1574 builder.end(); 1806 builder.end();
1575 1807
1576 return builder.getRoot(); 1808 return builder.getRoot();
1577 } 1809 }
1578 1810
1579 protected CodeTree createReturnRewriteAndInvoke(CodeTreeBuilder parent, String target, String message, SpecializationData source, SpecializationData current) { 1811 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, CodeTree replaceCall) {
1812 CodeTreeBuilder builder = parent.create();
1813 if (current.isGeneric()) {
1814 builder.startReturn().tree(replaceCall).string(".").startCall(EXECUTE_GENERIC_NAME);
1815 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true);
1816 builder.end().end();
1817
1818 } else if (current.getMethod() == null) {
1819 builder.statement(replaceCall);
1820 emitEncounteredSynthetic(builder, current);
1821 } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) {
1822 builder.statement(replaceCall);
1823 builder.startReturn().tree(createTemplateMethodCall(parent, null, source, current, null)).end();
1824 } else {
1825 replaceCall.add(new CodeTree(CodeTreeKind.STRING, null, "."));
1826 builder.startReturn().tree(createTemplateMethodCall(parent, replaceCall, source, current, null)).end();
1827 }
1828 return builder.getRoot();
1829 }
1830
1831 protected CodeTree createReplaceCall(CodeTreeBuilder builder, SpecializationData current, String target, String message) {
1580 String className = nodeSpecializationClassName(current); 1832 String className = nodeSpecializationClassName(current);
1581 CodeTreeBuilder builder = parent.create();
1582 CodeTreeBuilder replaceCall = builder.create(); 1833 CodeTreeBuilder replaceCall = builder.create();
1583 if (target != null) { 1834 if (target != null) {
1584 replaceCall.startCall(target, "replace"); 1835 replaceCall.startCall(target, "replace");
1585 } else { 1836 } else {
1586 replaceCall.startCall("replace"); 1837 replaceCall.startCall("replace");
1590 replaceCall.string("message"); 1841 replaceCall.string("message");
1591 } else { 1842 } else {
1592 replaceCall.doubleQuote(message); 1843 replaceCall.doubleQuote(message);
1593 } 1844 }
1594 replaceCall.end(); 1845 replaceCall.end();
1595 1846 return replaceCall.getRoot();
1596 if (current.isGeneric()) {
1597 replaceCall.string(".");
1598 builder.startReturn().tree(replaceCall.getRoot()).startCall(EXECUTE_GENERIC_NAME);
1599 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true);
1600 builder.end().end();
1601
1602 } else if (current.getMethod() == null) {
1603 builder.statement(replaceCall.getRoot());
1604 emitEncounteredSynthetic(builder, current);
1605 } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) {
1606 builder.statement(replaceCall.getRoot());
1607 builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
1608 } else {
1609 replaceCall.string(".");
1610 builder.startReturn().tree(createTemplateMethodCall(builder, replaceCall.getRoot(), source, current, null)).end();
1611 }
1612 return builder.getRoot();
1613 } 1847 }
1614 1848
1615 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { 1849 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) {
1616 String polyClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization()); 1850 String polyClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization());
1617 String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); 1851 String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
2259 builder.newLine(); 2493 builder.newLine();
2260 2494
2261 builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end(); 2495 builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end();
2262 builder.startBlock(); 2496 builder.startBlock();
2263 String message = ("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"); 2497 String message = ("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")");
2264 builder.tree(createReturnRewriteAndInvoke(builder, "root", message, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization())); 2498 builder.tree(createGenericInvoke(builder, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization(),
2499 createReplaceCall(builder, node.getGenericSpecialization(), "root", message)));
2265 builder.end(); 2500 builder.end();
2266 2501
2267 builder.startElseBlock(); 2502 builder.startElseBlock();
2268 builder.startStatement().startCall("setNext0"); 2503 builder.startStatement().startCall("setNext0");
2269 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); 2504 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
2487 return builder.getRoot(); 2722 return builder.getRoot();
2488 } 2723 }
2489 2724
2490 } 2725 }
2491 2726
2727 private interface CodeBlock<T> {
2728
2729 CodeTree create(CodeTreeBuilder parent, T value);
2730
2731 }
2492 } 2732 }