Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 11186:4a9936bb03a4
Truffle-DSL: Fixed executeAndSpecialize layout to always call specialization methods on the correct node. (GRAAL-379 #resolve)
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 30 Jul 2013 16:12:26 +0200 |
parents | 5daaa0821406 |
children | 7a8835ec5e7d |
comparison
equal
deleted
inserted
replaced
11185:5daaa0821406 | 11186:4a9936bb03a4 |
---|---|
30 import javax.lang.model.element.*; | 30 import javax.lang.model.element.*; |
31 import javax.lang.model.type.*; | 31 import javax.lang.model.type.*; |
32 import javax.lang.model.util.*; | 32 import javax.lang.model.util.*; |
33 | 33 |
34 import com.oracle.truffle.api.dsl.*; | 34 import com.oracle.truffle.api.dsl.*; |
35 import com.oracle.truffle.api.nodes.NodeInfo.Kind; | |
35 import com.oracle.truffle.api.nodes.*; | 36 import com.oracle.truffle.api.nodes.*; |
36 import com.oracle.truffle.api.nodes.NodeInfo.Kind; | |
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.template.*; | 41 import com.oracle.truffle.dsl.processor.template.*; |
42 import com.oracle.truffle.dsl.processor.template.TemplateMethod.*; | 42 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; |
43 import com.oracle.truffle.dsl.processor.typesystem.*; | 43 import com.oracle.truffle.dsl.processor.typesystem.*; |
44 | 44 |
45 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { | 45 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { |
46 | 46 |
47 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; | 47 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; |
1101 builder.statement("this.next0 = adoptChild(next0)"); | 1101 builder.statement("this.next0 = adoptChild(next0)"); |
1102 clazz.add(setter); | 1102 clazz.add(setter); |
1103 | 1103 |
1104 createIsCompatible(clazz, null); | 1104 createIsCompatible(clazz, null); |
1105 | 1105 |
1106 clazz.add(createCreateSpecialization(node)); | |
1107 | |
1108 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization(), null); | 1106 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization(), null); |
1109 clazz.add(genericCachedExecute); | 1107 clazz.add(genericCachedExecute); |
1110 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { | 1108 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { |
1111 if (polymorph == node.getGenericPolymorphicSpecialization()) { | 1109 if (polymorph == node.getGenericPolymorphicSpecialization()) { |
1112 continue; | 1110 continue; |
1238 String name = executeCachedName(polymorph); | 1236 String name = executeCachedName(polymorph); |
1239 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); | 1237 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); |
1240 | 1238 |
1241 ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); | 1239 ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); |
1242 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); | 1240 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); |
1241 if (sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { | |
1242 sourceThrowsUnexpected = false; | |
1243 } | |
1243 if (sourceThrowsUnexpected) { | 1244 if (sourceThrowsUnexpected) { |
1244 cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class)); | 1245 cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class)); |
1245 } | 1246 } |
1246 addInternalValueParameters(cachedExecute, polymorph, true, true); | 1247 addInternalValueParameters(cachedExecute, polymorph, true, true); |
1247 | 1248 |
1255 builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable)); | 1256 builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable)); |
1256 } | 1257 } |
1257 | 1258 |
1258 return cachedExecute; | 1259 return cachedExecute; |
1259 | 1260 |
1260 } | |
1261 | |
1262 private CodeExecutableElement createCreateSpecialization(NodeData node) { | |
1263 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), getElement().asType(), "createSpezialization0"); | |
1264 method.getParameters().add(new CodeVariableElement(context.getType(Class.class), "clazz")); | |
1265 CodeTreeBuilder builder = method.createBuilder(); | |
1266 | |
1267 builder.startStatement().type(getElement().asType()).string(" node").end(); | |
1268 | |
1269 boolean elseIf = false; | |
1270 for (SpecializationData specialization : node.getSpecializations()) { | |
1271 if (specialization.isGeneric() || specialization.isUninitialized()) { | |
1272 continue; | |
1273 } | |
1274 | |
1275 elseIf = builder.startIf(elseIf); | |
1276 builder.startGroup().string("clazz == ").string(nodeSpecializationClassName(specialization)).string(".class").end(); | |
1277 builder.end(); | |
1278 builder.startBlock(); | |
1279 builder.startStatement(); | |
1280 builder.string("node = "); | |
1281 builder.startNew(nodeSpecializationClassName(specialization)).string("this").end(); | |
1282 builder.end(); | |
1283 builder.end(); | |
1284 } | |
1285 | |
1286 builder.startElseBlock(); | |
1287 builder.startThrow().startNew(context.getType(AssertionError.class)).end().end(); | |
1288 builder.end(); | |
1289 | |
1290 builder.startStatement().startCall("node", "setNext0"); | |
1291 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); | |
1292 builder.end().end(); | |
1293 | |
1294 builder.startReturn().string("node").end(); | |
1295 | |
1296 return method; | |
1297 } | 1261 } |
1298 | 1262 |
1299 private void createConstructors(NodeData node, CodeTypeElement clazz) { | 1263 private void createConstructors(NodeData node, CodeTypeElement clazz) { |
1300 List<ExecutableElement> constructors = findUserConstructors(node.getNodeType()); | 1264 List<ExecutableElement> constructors = findUserConstructors(node.getNodeType()); |
1301 if (constructors.isEmpty()) { | 1265 if (constructors.isEmpty()) { |
1447 builder.startStatement(); | 1411 builder.startStatement(); |
1448 builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end(); | 1412 builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end(); |
1449 builder.end(); | 1413 builder.end(); |
1450 | 1414 |
1451 emitSpecializationListeners(builder, node); | 1415 emitSpecializationListeners(builder, node); |
1452 builder.defaultDeclaration(node.getGenericSpecialization().getReturnType().getTypeSystemType().getPrimitiveType(), "result"); | |
1453 | |
1454 builder.defaultDeclaration(getContext().getType(Class.class), "resultClass"); | |
1455 | 1416 |
1456 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); | 1417 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); |
1457 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true); | 1418 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true); |
1458 builder.end().end(); | 1419 builder.end().end(); |
1459 | |
1460 String prefix = null; | |
1461 | 1420 |
1462 List<SpecializationData> specializations = node.getSpecializations(); | 1421 List<SpecializationData> specializations = node.getSpecializations(); |
1463 | 1422 |
1464 boolean firstUnreachable = true; | 1423 boolean firstUnreachable = true; |
1465 SpecializationData previous = null; | 1424 SpecializationData previous = null; |
1466 for (SpecializationData current : specializations) { | 1425 for (SpecializationData current : specializations) { |
1467 if (current.isUninitialized()) { | 1426 if (current.isUninitialized()) { |
1468 continue; | 1427 continue; |
1428 } | |
1429 String prefix = null; | |
1430 | |
1431 if (current.hasRewrite(getContext())) { | |
1432 prefix = "minimumState < " + node.getSpecializations().indexOf(current); | |
1469 } | 1433 } |
1470 | 1434 |
1471 if (current.isReachable()) { | 1435 if (current.isReachable()) { |
1472 CodeTree execute = createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current); | 1436 CodeTree execute = createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current); |
1473 | 1437 |
1533 protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { | 1497 protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { |
1534 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1498 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1535 | 1499 |
1536 NodeData node = current.getNode(); | 1500 NodeData node = current.getNode(); |
1537 | 1501 |
1538 builder.startIf().string("resultClass == null").end().startBlock(); | 1502 if (current.isGeneric() && node.isPolymorphic()) { |
1539 if (current.getMethod() != null) { | 1503 builder.startIf().string("next0 == null && minimumState > 0").end().startBlock(); |
1540 CodeTree executeCall = createTemplateMethodCall(builder, null, source, current, null); | 1504 builder.tree(createRewritePolymorphic(builder, node)); |
1541 if (current.getReturnType().getTypeSystemType().isVoid()) { | 1505 builder.end(); |
1542 builder.statement(executeCall); | 1506 builder.startElseBlock(); |
1543 } else { | 1507 builder.tree(createRewriteGeneric(builder, source, current)); |
1544 builder.startStatement().string("result = ").tree(executeCall).end(); | |
1545 } | |
1546 builder.startStatement(); | |
1547 builder.string("resultClass = ").string(nodeSpecializationClassName(current)).string(".class"); | |
1548 builder.end(); | 1508 builder.end(); |
1549 } else { | 1509 } else { |
1550 emitEncounteredSynthetic(builder, current); | 1510 // simple rewrite |
1551 } | 1511 builder.tree(createReturnRewriteAndInvoke(builder, null, null, source, current)); |
1552 builder.end(); | |
1553 | |
1554 boolean ifAllowed = current.hasRewrite(getContext()); | |
1555 if (ifAllowed) { | |
1556 builder.startIf(); | |
1557 builder.string("minimumState < ").string(String.valueOf(node.getSpecializations().indexOf(current))); | |
1558 builder.end().startBlock(); | |
1559 } | |
1560 | |
1561 if (!current.isGeneric() || !node.isPolymorphic()) { | |
1562 // generic rewrite | |
1563 builder.tree(createRewriteGeneric(builder, current)); | |
1564 } else { | |
1565 boolean rewriteableToGeneric = node.getGenericSpecialization().getMethod() != null && node.getGenericSpecialization().isReachable(); | |
1566 if (rewriteableToGeneric) { | |
1567 builder.startIf().string("resultClass == ").string(nodeSpecializationClassName(node.getGenericSpecialization())).string(".class").end(); | |
1568 builder.startBlock(); | |
1569 | |
1570 if (node.isPolymorphic()) { | |
1571 builder.startIf().string("next0 == null").end(); | |
1572 builder.startBlock(); | |
1573 } | |
1574 builder.tree(createRewriteGeneric(builder, current)); | |
1575 | |
1576 if (node.isPolymorphic()) { | |
1577 builder.end().startElseBlock(); | |
1578 builder.statement("Node searchNode = super.getParent()"); | |
1579 builder.startWhile().string("searchNode != null").end(); | |
1580 builder.startBlock(); | |
1581 builder.statement("searchNode = searchNode.getParent()"); | |
1582 builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end(); | |
1583 builder.startBlock().breakStatement().end(); | |
1584 builder.end(); | |
1585 builder.startStatement().startCall("searchNode", "replace"); | |
1586 builder.startGroup().startNew(nodeSpecializationClassName(current)).startGroup().cast(baseClassName(node)).string("searchNode").end().end().end(); | |
1587 builder.string("message"); | |
1588 builder.end().end().end(); | |
1589 } | |
1590 | |
1591 builder.end().startElseBlock(); | |
1592 } | |
1593 | |
1594 // polymorphic rewrite | |
1595 builder.tree(createRewritePolymorphic(builder, node)); | |
1596 | |
1597 if (rewriteableToGeneric) { | |
1598 builder.end(); | |
1599 } | |
1600 } | |
1601 | |
1602 if (current.getReturnType().getTypeSystemType().isVoid()) { | |
1603 builder.returnStatement(); | |
1604 } else { | |
1605 builder.startReturn().string("result").end(); | |
1606 } | |
1607 if (ifAllowed) { | |
1608 builder.end(); | |
1609 } | 1512 } |
1610 | 1513 |
1611 return encloseThrowsWithFallThrough(current, builder.getRoot()); | 1514 return encloseThrowsWithFallThrough(current, builder.getRoot()); |
1515 } | |
1516 | |
1517 private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { | |
1518 NodeData node = current.getNode(); | |
1519 | |
1520 CodeTreeBuilder builder = parent.create(); | |
1521 builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this"); | |
1522 builder.startIf().string("next0 != null").end().startBlock(); | |
1523 builder.tree(createFindRoot(builder, node, false)); | |
1524 builder.end(); | |
1525 builder.end(); | |
1526 builder.tree(createReturnRewriteAndInvoke(builder, "root", null, source, current)); | |
1527 return builder.getRoot(); | |
1528 } | |
1529 | |
1530 protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) { | |
1531 CodeTreeBuilder builder = parent.create(); | |
1532 builder.startDoBlock(); | |
1533 builder.startAssert().string("root != null").string(" : ").doubleQuote("No polymorphic parent node.").end(); | |
1534 builder.startStatement().string("root = ").string("root.getParent()").end(); | |
1535 if (countDepth) { | |
1536 builder.statement("depth++"); | |
1537 } | |
1538 builder.end(); | |
1539 builder.startDoWhile(); | |
1540 builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end(); | |
1541 builder.end(); | |
1542 return builder.getRoot(); | |
1612 } | 1543 } |
1613 | 1544 |
1614 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { | 1545 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { |
1615 if (current.getExceptions().isEmpty()) { | 1546 if (current.getExceptions().isEmpty()) { |
1616 return tree; | 1547 return tree; |
1626 builder.end(); | 1557 builder.end(); |
1627 | 1558 |
1628 return builder.getRoot(); | 1559 return builder.getRoot(); |
1629 } | 1560 } |
1630 | 1561 |
1631 private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData current) { | 1562 protected CodeTree createReturnRewriteAndInvoke(CodeTreeBuilder parent, String target, String message, SpecializationData source, SpecializationData current) { |
1563 String className = nodeSpecializationClassName(current); | |
1632 CodeTreeBuilder builder = parent.create(); | 1564 CodeTreeBuilder builder = parent.create(); |
1633 builder.startStatement().startCall("super", "replace"); | 1565 CodeTreeBuilder replaceCall = builder.create(); |
1634 builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end(); | 1566 if (target != null) { |
1635 builder.string("message"); | 1567 replaceCall.startCall(target, "replace"); |
1636 builder.end().end(); | 1568 } else { |
1569 replaceCall.startCall("replace"); | |
1570 } | |
1571 replaceCall.startGroup().startNew(className).string("this").end().end(); | |
1572 if (message == null) { | |
1573 replaceCall.string("message"); | |
1574 } else { | |
1575 replaceCall.doubleQuote(message); | |
1576 } | |
1577 replaceCall.end(); | |
1578 | |
1579 if (current.isGeneric()) { | |
1580 replaceCall.string("."); | |
1581 builder.startReturn().tree(replaceCall.getRoot()).startCall(EXECUTE_GENERIC_NAME); | |
1582 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true); | |
1583 builder.end().end(); | |
1584 | |
1585 } else if (current.getMethod() == null) { | |
1586 builder.statement(replaceCall.getRoot()); | |
1587 emitEncounteredSynthetic(builder, current); | |
1588 } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) { | |
1589 builder.statement(replaceCall.getRoot()); | |
1590 builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end(); | |
1591 } else { | |
1592 replaceCall.string("."); | |
1593 builder.startReturn().tree(createTemplateMethodCall(builder, replaceCall.getRoot(), source, current, null)).end(); | |
1594 } | |
1637 return builder.getRoot(); | 1595 return builder.getRoot(); |
1638 } | 1596 } |
1639 | 1597 |
1640 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { | 1598 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { |
1641 String className = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization()); | 1599 String polyClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization()); |
1600 String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); | |
1642 CodeTreeBuilder builder = parent.create(); | 1601 CodeTreeBuilder builder = parent.create(); |
1643 builder.startStatement(); | 1602 |
1644 builder.string(className); | 1603 builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string("this").end()); |
1645 builder.string(" polymorphic = "); | |
1646 builder.startNew(className).string("this").end(); | |
1647 builder.end(); | |
1648 | 1604 |
1649 for (ActualParameter param : node.getGenericSpecialization().getParameters()) { | 1605 for (ActualParameter param : node.getGenericSpecialization().getParameters()) { |
1650 if (!param.getSpecification().isSignature()) { | 1606 if (!param.getSpecification().isSignature()) { |
1651 continue; | 1607 continue; |
1652 } | 1608 } |
1657 builder.string("[").string(String.valueOf(param.getIndex())).string("]"); | 1613 builder.string("[").string(String.valueOf(param.getIndex())).string("]"); |
1658 } | 1614 } |
1659 builder.string(" = null").end(); | 1615 builder.string(" = null").end(); |
1660 } | 1616 } |
1661 } | 1617 } |
1662 builder.startStatement().startCall("super", "replace"); | 1618 builder.startStatement().startCall("super", "replace").string("polymorphic").string("message").end().end(); |
1663 builder.string("polymorphic"); | 1619 builder.startStatement().startCall("polymorphic", "setNext0").string("this").end().end(); |
1664 builder.string("message"); | 1620 builder.startStatement().startCall("setNext0").startNew(uninitializedName).string("this").end().end().end(); |
1665 builder.end().end(); | 1621 |
1666 | 1622 builder.startReturn(); |
1667 builder.statement("polymorphic.setNext0(this)"); | 1623 builder.startCall("next0", executeCachedName(node.getGenericPolymorphicSpecialization())); |
1668 builder.statement("setNext0(createSpezialization0(resultClass))"); | 1624 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true); |
1669 | 1625 builder.end(); |
1670 builder.statement("polymorphic.optimizeTypes()"); | 1626 builder.end(); |
1627 | |
1671 return builder.getRoot(); | 1628 return builder.getRoot(); |
1672 } | 1629 } |
1673 | 1630 |
1674 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { | 1631 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { |
1675 for (TemplateMethod listener : node.getSpecializationListeners()) { | 1632 for (TemplateMethod listener : node.getSpecializationListeners()) { |
1877 builder.tree(createDeoptimize(builder)); | 1834 builder.tree(createDeoptimize(builder)); |
1878 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); | 1835 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); |
1879 if (specialization.isPolymorphic()) { | 1836 if (specialization.isPolymorphic()) { |
1880 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); | 1837 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); |
1881 } else { | 1838 } else { |
1882 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, "Expected " + param.getLocalName() + " instanceof " + | 1839 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param, |
1883 Utils.getSimpleName(param.getType()))); | 1840 "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); |
1884 } | 1841 } |
1885 builder.end(); // catch block | 1842 builder.end(); // catch block |
1886 } | 1843 } |
1887 | 1844 |
1888 return builder.getRoot(); | 1845 return builder.getRoot(); |
2030 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end(); | 1987 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end(); |
2031 builder.end(); | 1988 builder.end(); |
2032 return builder.getRoot(); | 1989 return builder.getRoot(); |
2033 } | 1990 } |
2034 | 1991 |
2035 protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) { | 1992 protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData current, ActualParameter exceptionParam, String reason) { |
2036 NodeData node = getModel().getNode(); | 1993 NodeData node = current.getNode(); |
2037 SpecializationData generic = node.getGenericSpecialization(); | 1994 SpecializationData generic = node.getGenericSpecialization(); |
2038 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); | 1995 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); |
2039 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); | 1996 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); |
2040 specializeCall.string(String.valueOf(node.getSpecializations().indexOf(nextSpecialization))); | 1997 specializeCall.string(String.valueOf(node.getSpecializations().indexOf(current))); |
2041 addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); | 1998 addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); |
2042 specializeCall.doubleQuote(reason); | 1999 specializeCall.doubleQuote(reason); |
2043 specializeCall.end().end(); | 2000 specializeCall.end().end(); |
2044 | 2001 |
2045 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2002 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2046 | 2003 |
2047 builder.startReturn(); | 2004 builder.startReturn(); |
2048 builder.tree(createExpectExecutableType(nextSpecialization.getNode(), generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); | 2005 builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); |
2049 builder.end(); | 2006 builder.end(); |
2050 | 2007 |
2051 return builder.getRoot(); | 2008 return builder.getRoot(); |
2052 } | 2009 } |
2053 } | 2010 } |
2273 } | 2230 } |
2274 } | 2231 } |
2275 | 2232 |
2276 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { | 2233 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { |
2277 NodeData node = specialization.getNode(); | 2234 NodeData node = specialization.getNode(); |
2278 String genericClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization()); | |
2279 | 2235 |
2280 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2236 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2281 builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); | 2237 builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); |
2282 | 2238 |
2283 builder.declaration(getContext().getTruffleTypes().getNode(), "searchNode", "super.getParent()"); | 2239 builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this"); |
2284 builder.declaration(getContext().getType(int.class), "depth", "0"); | 2240 builder.declaration(getContext().getType(int.class), "depth", "0"); |
2285 builder.startWhile().string("searchNode != null").end(); | 2241 builder.tree(createFindRoot(builder, node, true)); |
2242 builder.newLine(); | |
2243 | |
2244 builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end(); | |
2286 builder.startBlock(); | 2245 builder.startBlock(); |
2287 builder.statement("depth++"); | 2246 String message = ("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"); |
2288 builder.statement("searchNode = searchNode.getParent()"); | 2247 builder.tree(createReturnRewriteAndInvoke(builder, "root", message, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization())); |
2289 | 2248 builder.end(); |
2290 builder.startIf().instanceOf("searchNode", genericClassName).end(); | 2249 |
2291 builder.startBlock().breakStatement().end(); | 2250 builder.startElseBlock(); |
2292 builder.end(); // if | 2251 builder.startStatement().startCall("setNext0"); |
2293 builder.end(); // while | |
2294 | |
2295 builder.startAssert().instanceOf("searchNode", genericClassName).end(); | |
2296 | |
2297 builder.startStatement(); | |
2298 builder.string(genericClassName).string(" ").string("polymorphic = ").string("(").string(genericClassName).string(") searchNode"); | |
2299 builder.end(); | |
2300 | |
2301 builder.startIf().string("depth >= ").string(String.valueOf(node.getPolymorphicDepth())).end(); | |
2302 builder.startBlock(); | |
2303 builder.startStatement(); | |
2304 builder.startCall("searchNode", "replace"); | |
2305 builder.startNew(nodeSpecializationClassName(node.getGenericSpecialization())).string("this").end(); | |
2306 builder.doubleQuote("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"); | |
2307 builder.end(); | |
2308 builder.end(); | |
2309 | |
2310 builder.startReturn().startCall("super", EXECUTE_GENERIC_NAME); | |
2311 addInternalValueParameterNames(builder, specialization, node.getGenericSpecialization(), null, node.needsFrame(), true); | |
2312 builder.end().end(); | |
2313 | |
2314 builder.end().startElseBlock(); | |
2315 builder.startStatement().startCall("super", "setNext0"); | |
2316 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); | 2252 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); |
2317 builder.end().end(); | 2253 builder.end().end(); |
2318 | 2254 |
2319 CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder); | 2255 CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder); |
2320 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); | 2256 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); |
2323 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); | 2259 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); |
2324 specializeCall.end().end(); | 2260 specializeCall.end().end(); |
2325 | 2261 |
2326 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); | 2262 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); |
2327 | 2263 |
2328 builder.statement("polymorphic.optimizeTypes()"); | 2264 builder.startStatement().string("(").cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root).optimizeTypes()").end(); |
2329 | 2265 |
2330 if (Utils.isVoid(builder.findMethod().getReturnType())) { | 2266 if (Utils.isVoid(builder.findMethod().getReturnType())) { |
2331 builder.returnStatement(); | 2267 builder.returnStatement(); |
2332 } else { | 2268 } else { |
2333 builder.startReturn().string("result").end(); | 2269 builder.startReturn().string("result").end(); |
2431 | 2367 |
2432 builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); | 2368 builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); |
2433 | 2369 |
2434 CodeTree executeNode = createExecute(builder, executable, specialization); | 2370 CodeTree executeNode = createExecute(builder, executable, specialization); |
2435 | 2371 |
2436 SpecializationData next = specialization.findNextSpecialization(); | |
2437 CodeTree returnSpecialized = null; | 2372 CodeTree returnSpecialized = null; |
2438 if (next != null) { | 2373 |
2374 if (specialization.findNextSpecialization() != null) { | |
2439 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); | 2375 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); |
2440 returnBuilder.tree(createDeoptimize(builder)); | 2376 returnBuilder.tree(createDeoptimize(builder)); |
2441 returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed")); | 2377 returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, specialization, null, "One of guards " + specialization.getGuards() + " failed")); |
2442 returnSpecialized = returnBuilder.getRoot(); | 2378 returnSpecialized = returnBuilder.getRoot(); |
2443 } | 2379 } |
2380 | |
2444 builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false, false)); | 2381 builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false, false)); |
2445 | 2382 |
2446 return builder.getRoot(); | 2383 return builder.getRoot(); |
2447 } | 2384 } |
2448 | 2385 |
2518 | 2455 |
2519 if (!specialization.getExceptions().isEmpty()) { | 2456 if (!specialization.getExceptions().isEmpty()) { |
2520 for (SpecializationThrowsData exception : specialization.getExceptions()) { | 2457 for (SpecializationThrowsData exception : specialization.getExceptions()) { |
2521 builder.end().startCatchBlock(exception.getJavaClass(), "ex"); | 2458 builder.end().startCatchBlock(exception.getJavaClass(), "ex"); |
2522 builder.tree(createDeoptimize(builder)); | 2459 builder.tree(createDeoptimize(builder)); |
2523 builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); | 2460 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); |
2524 } | 2461 } |
2525 builder.end(); | 2462 builder.end(); |
2526 } | 2463 } |
2527 if (!specialization.getAssumptions().isEmpty()) { | 2464 if (!specialization.getAssumptions().isEmpty()) { |
2528 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); | 2465 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); |
2529 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed")); | 2466 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Assumption failed")); |
2530 builder.end(); | 2467 builder.end(); |
2531 } | 2468 } |
2532 | 2469 |
2533 return builder.getRoot(); | 2470 return builder.getRoot(); |
2534 } | 2471 } |