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 }