Mercurial > hg > graal-compiler
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 } |