Mercurial > hg > graal-compiler
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(); |