comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java @ 19291:f4792a544170

Truffle-DSL: implement new assumptions semantics.
author Christian Humer <christian.humer@gmail.com>
date Wed, 11 Feb 2015 12:13:44 +0100
parents 62c43fcf5be2
children 21b9b9941775
comparison
equal deleted inserted replaced
19290:bf166845c7d8 19291:f4792a544170
30 30
31 import javax.lang.model.element.*; 31 import javax.lang.model.element.*;
32 import javax.lang.model.type.*; 32 import javax.lang.model.type.*;
33 import javax.lang.model.util.*; 33 import javax.lang.model.util.*;
34 34
35 import com.oracle.truffle.api.*;
36 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; 35 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
37 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 36 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
38 import com.oracle.truffle.api.dsl.*; 37 import com.oracle.truffle.api.dsl.*;
39 import com.oracle.truffle.api.dsl.internal.*; 38 import com.oracle.truffle.api.dsl.internal.*;
40 import com.oracle.truffle.api.dsl.internal.DSLOptions.ImplicitCastOptimization; 39 import com.oracle.truffle.api.dsl.internal.DSLOptions.ImplicitCastOptimization;
72 this.node = node; 71 this.node = node;
73 this.typeSystem = node.getTypeSystem(); 72 this.typeSystem = node.getTypeSystem();
74 this.genericType = typeSystem.getGenericTypeData(); 73 this.genericType = typeSystem.getGenericTypeData();
75 this.options = typeSystem.getOptions(); 74 this.options = typeSystem.getOptions();
76 this.singleSpecializable = isSingleSpecializableImpl(); 75 this.singleSpecializable = isSingleSpecializableImpl();
77 this.varArgsThreshold = calculateVarArgsThresHold(); 76 this.varArgsThreshold = calculateVarArgsThreshold();
78 77 }
79 } 78
80 79 private int calculateVarArgsThreshold() {
81 private int calculateVarArgsThresHold() {
82 TypeMirror specialization = context.getType(SpecializationNode.class); 80 TypeMirror specialization = context.getType(SpecializationNode.class);
83 TypeElement specializationType = fromTypeMirror(specialization); 81 TypeElement specializationType = fromTypeMirror(specialization);
84 82
85 int maxParameters = 0; 83 int maxParameters = 0;
86 for (ExecutableElement element : ElementFilter.methodsIn(specializationType.getEnclosedElements())) { 84 for (ExecutableElement element : ElementFilter.methodsIn(specializationType.getEnclosedElements())) {
91 return maxParameters; 89 return maxParameters;
92 } 90 }
93 91
94 public static String nodeTypeName(NodeData node) { 92 public static String nodeTypeName(NodeData node) {
95 return resolveNodeId(node) + NODE_SUFFIX; 93 return resolveNodeId(node) + NODE_SUFFIX;
94 }
95
96 private static String assumptionName(AssumptionExpression assumption) {
97 return assumption.getId() + NAME_SUFFIX;
96 } 98 }
97 99
98 private static String resolveNodeId(NodeData node) { 100 private static String resolveNodeId(NodeData node) {
99 String nodeid = node.getNodeId(); 101 String nodeid = node.getNodeId();
100 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { 102 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
155 return CodeTreeBuilder.createBuilder().string("root.").string(name).build(); 157 return CodeTreeBuilder.createBuilder().string("root.").string(name).build();
156 } 158 }
157 } 159 }
158 } 160 }
159 161
160 private static String assumptionName(String assumption) {
161 return assumption + "_";
162 }
163
164 public CodeTypeElement create() { 162 public CodeTypeElement create() {
165 CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(FINAL), nodeTypeName(node), node.getTemplateType().asType()); 163 CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(FINAL), nodeTypeName(node), node.getTemplateType().asType());
166 ElementUtils.setVisibility(clazz.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers())); 164 ElementUtils.setVisibility(clazz.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
167
168 for (String assumption : node.getAssumptions()) {
169 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getType(Assumption.class), assumptionName(assumption)));
170 }
171 165
172 for (NodeChildData child : node.getChildren()) { 166 for (NodeChildData child : node.getChildren()) {
173 clazz.addOptional(createAccessChildMethod(child)); 167 clazz.addOptional(createAccessChildMethod(child));
174 } 168 }
175 169
755 TypeData type = parameter.getTypeSystemType(); 749 TypeData type = parameter.getTypeSystemType();
756 if (type != null && type.hasImplicitSourceTypes()) { 750 if (type != null && type.hasImplicitSourceTypes()) {
757 return false; 751 return false;
758 } 752 }
759 } 753 }
754
755 if (!specialization.getAssumptionExpressions().isEmpty()) {
756 return false;
757 }
758
760 if (specialization.getCaches().size() > 0) { 759 if (specialization.getCaches().size() > 0) {
761 // TODO chumer: caches do not yet support single specialization. 760 // TODO chumer: caches do not yet support single specialization.
762 // it could be worthwhile to explore if this is possible 761 // it could be worthwhile to explore if this is possible
763 return false; 762 return false;
764 } 763 }
828 SpecializationData specialization = getReachableSpecializations().iterator().next(); 827 SpecializationData specialization = getReachableSpecializations().iterator().next();
829 ExecutableTypeData wrappedExecutableType = findWrappedExecutable(specialization, implementedExecutables, execType); 828 ExecutableTypeData wrappedExecutableType = findWrappedExecutable(specialization, implementedExecutables, execType);
830 if (wrappedExecutableType != null) { 829 if (wrappedExecutableType != null) {
831 builder.startReturn().tree(callTemplateMethod(null, wrappedExecutableType, locals)).end(); 830 builder.startReturn().tree(callTemplateMethod(null, wrappedExecutableType, locals)).end();
832 } else { 831 } else {
833 builder.tree(createFastPathExecute(builder, specialization, execType.getType(), locals)); 832 builder.tree(createFastPath(builder, specialization, execType.getType(), locals));
834 } 833 }
835 } else { 834 } else {
836 // create acceptAndExecute 835 // create acceptAndExecute
837 CodeTreeBuilder executeBuilder = builder.create(); 836 CodeTreeBuilder executeBuilder = builder.create();
838 executeBuilder.startCall(specializationStartFieldName(), TypeSystemNodeFactory.executeName(executedType)); 837 executeBuilder.startCall(specializationStartFieldName(), TypeSystemNodeFactory.executeName(executedType));
986 if (tree != null) { 985 if (tree != null) {
987 builder.tree(tree); 986 builder.tree(tree);
988 continue; 987 continue;
989 } 988 }
990 } 989 }
991 builder.string(parameter.getLocalName()); 990
991 builder.defaultValue(parameter.getType());
992 } 992 }
993 builder.end(); 993 builder.end();
994 return builder.build(); 994 return builder.build();
995 } 995 }
996 996
1034 } 1034 }
1035 1035
1036 if (node.isFrameUsedByAnyGuard()) { 1036 if (node.isFrameUsedByAnyGuard()) {
1037 builder.tree(createTransferToInterpreterAndInvalidate()); 1037 builder.tree(createTransferToInterpreterAndInvalidate());
1038 } 1038 }
1039
1040 boolean hasAssumptions = !specialization.getAssumptionExpressions().isEmpty();
1041 if (hasAssumptions) {
1042 for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
1043 CodeTree assumptions = DSLExpressionGenerator.write(assumption.getExpression(), accessParent(null),
1044 castBoundTypes(bindExpressionValues(assumption.getExpression(), specialization, currentValues)));
1045 String name = assumptionName(assumption);
1046 // needs specialization index for assumption to make unique
1047 String varName = name + specialization.getIndex();
1048 TypeMirror type = assumption.getExpression().getResolvedType();
1049 builder.declaration(type, varName, assumptions);
1050 currentValues.set(name, new LocalVariable(null, type, varName, null));
1051 }
1052
1053 builder.startIf();
1054 String sep = "";
1055 for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
1056 LocalVariable assumptionVar = currentValues.get(assumptionName(assumption));
1057 if (assumptionVar == null) {
1058 throw new AssertionError("assumption var not resolved");
1059 }
1060 builder.string(sep);
1061 builder.startCall("isValid").tree(assumptionVar.createReference()).end();
1062 sep = " && ";
1063 }
1064 builder.end();
1065 builder.startBlock();
1066 }
1067
1039 for (SpecializationData otherSpeciailzation : node.getSpecializations()) { 1068 for (SpecializationData otherSpeciailzation : node.getSpecializations()) {
1040 if (otherSpeciailzation == specialization) { 1069 if (otherSpeciailzation == specialization) {
1041 continue; 1070 continue;
1042 } 1071 }
1043 if (otherSpeciailzation.getExcludedBy().contains(specialization)) { 1072 if (otherSpeciailzation.getExcludedBy().contains(specialization)) {
1050 1079
1051 CodeTree create = createCallCreateMethod(specialization, null, currentValues); 1080 CodeTree create = createCallCreateMethod(specialization, null, currentValues);
1052 1081
1053 if (specialization.hasMultipleInstances()) { 1082 if (specialization.hasMultipleInstances()) {
1054 builder.declaration(getType(SpecializationNode.class), "s", create); 1083 builder.declaration(getType(SpecializationNode.class), "s", create);
1055
1056 DSLExpression limitExpression = specialization.getLimitExpression(); 1084 DSLExpression limitExpression = specialization.getLimitExpression();
1057 CodeTree limitExpressionTree; 1085 CodeTree limitExpressionTree;
1058 if (limitExpression == null) { 1086 if (limitExpression == null) {
1059 limitExpressionTree = CodeTreeBuilder.singleString("3"); 1087 limitExpressionTree = CodeTreeBuilder.singleString("3");
1060 } else { 1088 } else {
1063 } 1091 }
1064 1092
1065 builder.startIf().string("countSame(s) < ").tree(limitExpressionTree).end().startBlock(); 1093 builder.startIf().string("countSame(s) < ").tree(limitExpressionTree).end().startBlock();
1066 builder.statement("return s"); 1094 builder.statement("return s");
1067 builder.end(); 1095 builder.end();
1068
1069 } else { 1096 } else {
1070 builder.startReturn().tree(create).end(); 1097 builder.startReturn().tree(create).end();
1098 }
1099
1100 if (hasAssumptions) {
1101 builder.end();
1071 } 1102 }
1072 1103
1073 if (mayBeExcluded(specialization)) { 1104 if (mayBeExcluded(specialization)) {
1074 CodeTreeBuilder checkHasSeenBuilder = builder.create(); 1105 CodeTreeBuilder checkHasSeenBuilder = builder.create();
1075 checkHasSeenBuilder.startIf().string("!").tree(accessParent(excludedFieldName(specialization))).end().startBlock(); 1106 checkHasSeenBuilder.startIf().string("!").tree(accessParent(excludedFieldName(specialization))).end().startBlock();
1110 1141
1111 if (!guards.isEmpty()) { 1142 if (!guards.isEmpty()) {
1112 return true; 1143 return true;
1113 } 1144 }
1114 1145
1115 if ((!fastPath || forType.isGeneric()) && !group.getAssumptions().isEmpty()) { 1146 if (!fastPath && specialization != null && !specialization.getAssumptionExpressions().isEmpty()) {
1116 return true; 1147 return true;
1117 } 1148 }
1118 1149
1119 if (!fastPath && specialization != null && mayBeExcluded(specialization)) { 1150 if (!fastPath && specialization != null && mayBeExcluded(specialization)) {
1120 return true; 1151 return true;
1191 if (variable == null) { 1222 if (variable == null) {
1192 throw new AssertionError("Could not bind cached value " + cache.getParameter().getLocalName() + ": " + currentValues); 1223 throw new AssertionError("Could not bind cached value " + cache.getParameter().getLocalName() + ": " + currentValues);
1193 } 1224 }
1194 builder.tree(variable.createReference()); 1225 builder.tree(variable.createReference());
1195 } 1226 }
1196 1227 for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
1228 LocalVariable variable = currentValues.get(assumptionName(assumption));
1229 if (variable == null) {
1230 throw new AssertionError("Could not bind assumption value " + assumption.getId() + ": " + currentValues);
1231 }
1232 builder.tree(variable.createReference());
1233 }
1197 } 1234 }
1198 builder.end(); 1235 builder.end();
1199 1236
1200 return builder.build(); 1237 return builder.build();
1201 } 1238 }
1285 } 1322 }
1286 constructor.addParameter(new CodeVariableElement(type, name)); 1323 constructor.addParameter(new CodeVariableElement(type, name));
1287 builder.startStatement().string("this.").string(name).string(" = ").string(name).end(); 1324 builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
1288 } 1325 }
1289 1326
1327 for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
1328 String name = assumptionName(assumption);
1329 TypeMirror type = assumption.getExpression().getResolvedType();
1330 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name));
1331 constructor.addParameter(new CodeVariableElement(type, name));
1332 builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
1333 }
1290 } 1334 }
1291 1335
1292 if (constructor.getParameters().isEmpty()) { 1336 if (constructor.getParameters().isEmpty()) {
1293 // do not generate default constructor 1337 // do not generate default constructor
1294 return null; 1338 return null;
1344 builder.tree(TypeSystemCodeGenerator.expect(genericType, forType, call)); 1388 builder.tree(TypeSystemCodeGenerator.expect(genericType, forType, call));
1345 builder.end(); 1389 builder.end();
1346 return builder.build(); 1390 return builder.build();
1347 } 1391 }
1348 1392
1349 private static CodeTree createCallDelegate(String methodName, TypeData forType, LocalContext currentValues) { 1393 private static CodeTree createCallDelegate(String methodName, String reason, TypeData forType, LocalContext currentValues) {
1350 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 1394 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1351 builder.startCall(methodName); 1395 builder.startCall(methodName);
1396 if (reason != null) {
1397 builder.doubleQuote(reason);
1398 }
1352 currentValues.addReferencesTo(builder, FRAME_VALUE); 1399 currentValues.addReferencesTo(builder, FRAME_VALUE);
1353 builder.end(); 1400 builder.end();
1354 1401
1355 TypeData executedType = forType.getTypeSystem().getGenericTypeData(); 1402 TypeData executedType = forType.getTypeSystem().getGenericTypeData();
1356 return TypeSystemCodeGenerator.expect(executedType, forType, builder.build()); 1403 return TypeSystemCodeGenerator.expect(executedType, forType, builder.build());
1387 private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeData forType, int evaluatedArguments) { 1434 private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeData forType, int evaluatedArguments) {
1388 TypeData type = forType == null ? genericType : forType; 1435 TypeData type = forType == null ? genericType : forType;
1389 LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold); 1436 LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold);
1390 1437
1391 if (specialization != null) { 1438 if (specialization != null) {
1392 currentLocals.loadFastPathCachedValues(specialization); 1439 currentLocals.loadFastPathState(specialization);
1393 } 1440 }
1394 1441
1395 CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE); 1442 CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE);
1396 executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); 1443 executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
1397 1444
1398 if (!type.isGeneric()) { 1445 if (!type.isGeneric()) {
1399 executable.getThrownTypes().add(getType(UnexpectedResultException.class)); 1446 executable.getThrownTypes().add(getType(UnexpectedResultException.class));
1400 } 1447 }
1401 1448
1402 CodeTreeBuilder builder = executable.createBuilder(); 1449 CodeTreeBuilder builder = executable.createBuilder();
1403 builder.tree(createFastPathExecute(builder, specialization, type, currentLocals)); 1450 builder.tree(createFastPath(builder, specialization, type, currentLocals));
1404 1451
1405 return executable; 1452 return executable;
1406 } 1453 }
1407 1454
1408 private CodeTree createFastPathExecute(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) { 1455 private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) {
1409 final CodeTreeBuilder builder = parent.create(); 1456 final CodeTreeBuilder builder = parent.create();
1410 1457
1411 for (NodeExecutionData execution : node.getChildExecutions()) { 1458 for (NodeExecutionData execution : node.getChildExecutions()) {
1412 LocalVariable var = currentLocals.getValue(execution); 1459 LocalVariable var = currentLocals.getValue(execution);
1413 if (var == null) { 1460 if (var == null) {
1424 } 1471 }
1425 } 1472 }
1426 1473
1427 LocalContext originalValues = currentLocals.copy(); 1474 LocalContext originalValues = currentLocals.copy();
1428 if (specialization == null) { 1475 if (specialization == null) {
1429 builder.startReturn().tree(createCallDelegate("acceptAndExecute", type, currentLocals)).end(); 1476 builder.startReturn().tree(createCallDelegate("acceptAndExecute", null, type, currentLocals)).end();
1430 } else if (specialization.isPolymorphic()) { 1477 } else if (specialization.isPolymorphic()) {
1431 builder.tree(createCallNext(type, currentLocals)); 1478 builder.tree(createCallNext(type, currentLocals));
1432 } else if (specialization.isUninitialized()) { 1479 } else if (specialization.isUninitialized()) {
1433 builder.startReturn().tree(createCallDelegate("uninitialized", type, currentLocals)).end(); 1480 builder.startReturn().tree(createCallDelegate("uninitialized", null, type, currentLocals)).end();
1434 } else { 1481 } else {
1435 final TypeData finalType = type; 1482 final TypeData finalType = type;
1436 SpecializationGroup group = SpecializationGroup.create(specialization); 1483 SpecializationGroup group = SpecializationGroup.create(specialization);
1437 SpecializationExecution executionFactory = new SpecializationExecution() { 1484 SpecializationExecution executionFactory = new SpecializationExecution() {
1438 public CodeTree createExecute(SpecializationData s, LocalContext values) { 1485 public CodeTree createExecute(SpecializationData s, LocalContext values) {
1493 builder.end(); 1540 builder.end();
1494 builder.startBlock(); 1541 builder.startBlock();
1495 ifCount++; 1542 ifCount++;
1496 } 1543 }
1497 CodeTreeBuilder execute = builder.create(); 1544 CodeTreeBuilder execute = builder.create();
1545
1546 if (!specialization.getAssumptionExpressions().isEmpty()) {
1547 builder.startTryBlock();
1548 for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
1549 LocalVariable assumptionVar = currentValues.get(assumptionName(assumption));
1550 if (assumptionVar == null) {
1551 throw new AssertionError("Could not resolve assumption var " + currentValues);
1552 }
1553 builder.startStatement().startCall("check").tree(assumptionVar.createReference()).end().end();
1554 }
1555 builder.end().startCatchBlock(getType(InvalidAssumptionException.class), "ae");
1556 builder.startReturn();
1557 List<String> assumptionIds = new ArrayList<>();
1558 for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
1559 assumptionIds.add(assumption.getId());
1560 }
1561 builder.tree(createCallDelegate("removeThis", String.format("Assumption %s invalidated", assumptionIds), forType, currentValues));
1562 builder.end();
1563 builder.end();
1564 }
1565
1498 execute.startReturn(); 1566 execute.startReturn();
1499 if (specialization.getMethod() == null) { 1567 if (specialization.getMethod() == null) {
1500 execute.startCall("unsupported"); 1568 execute.startCall("unsupported");
1501 currentValues.addReferencesTo(execute, FRAME_VALUE); 1569 currentValues.addReferencesTo(execute, FRAME_VALUE);
1502 execute.end(); 1570 execute.end();
1523 } 1591 }
1524 } 1592 }
1525 } 1593 }
1526 1594
1527 SpecializationData specialization = group.getSpecialization(); 1595 SpecializationData specialization = group.getSpecialization();
1528 CodeTree[] checkAndCast = createTypeCheckCastAndCaches(specialization, group.getTypeGuards(), castGuards, currentValues, execution); 1596 CodeTree[] checkAndCast = createTypeCheckAndLocals(specialization, group.getTypeGuards(), castGuards, currentValues, execution);
1529 1597
1530 CodeTree check = checkAndCast[0]; 1598 CodeTree check = checkAndCast[0];
1531 CodeTree cast = checkAndCast[1]; 1599 CodeTree cast = checkAndCast[1];
1532 1600
1533 List<GuardExpression> elseGuardExpressions = group.findElseConnectableGuards(); 1601 List<GuardExpression> elseGuardExpressions = group.findElseConnectableGuards();
1534 List<GuardExpression> guardExpressions = new ArrayList<>(group.getGuards()); 1602 List<GuardExpression> guardExpressions = new ArrayList<>(group.getGuards());
1535 guardExpressions.removeAll(elseGuardExpressions); 1603 guardExpressions.removeAll(elseGuardExpressions);
1536 CodeTree[] methodGuardAndAssertions = createMethodGuardCheck(guardExpressions, specialization, currentValues, execution.isFastPath()); 1604 CodeTree[] methodGuardAndAssertions = createMethodGuardCheck(guardExpressions, specialization, currentValues, execution.isFastPath());
1537 CodeTree methodGuards = methodGuardAndAssertions[0]; 1605 CodeTree methodGuards = methodGuardAndAssertions[0];
1538 CodeTree guardAssertions = methodGuardAndAssertions[1]; 1606 CodeTree guardAssertions = methodGuardAndAssertions[1];
1539
1540 if (!group.getAssumptions().isEmpty()) {
1541 if (execution.isFastPath() && !forType.isGeneric()) {
1542 cast = appendAssumptionFastPath(cast, group.getAssumptions(), forType, currentValues);
1543 } else {
1544 methodGuards = appendAssumptionSlowPath(methodGuards, group.getAssumptions());
1545 }
1546 }
1547 1607
1548 int ifCount = 0; 1608 int ifCount = 0;
1549 if (!check.isEmpty()) { 1609 if (!check.isEmpty()) {
1550 builder.startIf(); 1610 builder.startIf();
1551 builder.tree(check).end(); 1611 builder.tree(check).end();
1581 builder.end(ifCount); 1641 builder.end(ifCount);
1582 1642
1583 return builder.build(); 1643 return builder.build();
1584 } 1644 }
1585 1645
1586 private CodeTree appendAssumptionSlowPath(CodeTree methodGuards, List<String> assumptions) {
1587 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1588
1589 builder.tree(methodGuards);
1590 String connect = methodGuards.isEmpty() ? "" : " && ";
1591 for (String assumption : assumptions) {
1592 builder.string(connect);
1593 builder.startCall(accessParent(assumptionName(assumption)), "isValid").end();
1594 connect = " && ";
1595 }
1596
1597 return builder.build();
1598 }
1599
1600 private CodeTree appendAssumptionFastPath(CodeTree casts, List<String> assumptions, TypeData forType, LocalContext currentValues) {
1601 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1602 builder.tree(casts);
1603 builder.startTryBlock();
1604 for (String assumption : assumptions) {
1605 builder.startStatement().startCall(accessParent(assumptionName(assumption)), "check").end().end();
1606 }
1607 builder.end().startCatchBlock(getType(InvalidAssumptionException.class), "ae");
1608 builder.tree(createCallNext(forType, currentValues));
1609 builder.end();
1610 return builder.build();
1611 }
1612
1613 private static boolean isReachableGroup(SpecializationGroup group, int ifCount) { 1646 private static boolean isReachableGroup(SpecializationGroup group, int ifCount) {
1614 if (ifCount != 0) { 1647 if (ifCount != 0) {
1615 return true; 1648 return true;
1616 } 1649 }
1617 SpecializationGroup previous = group.getPreviousGroup(); 1650 SpecializationGroup previous = group.getPreviousGroup();
1621 1654
1622 /* 1655 /*
1623 * Hacky else case. In this case the specialization is not reachable due to previous else 1656 * Hacky else case. In this case the specialization is not reachable due to previous else
1624 * branch. This is only true if the minimum state is not checked. 1657 * branch. This is only true if the minimum state is not checked.
1625 */ 1658 */
1626 if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && 1659 if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() &&
1627 (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) { 1660 (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
1628 return false; 1661 return false;
1629 } 1662 }
1630 1663
1631 return true; 1664 return true;
2122 } 2155 }
2123 } 2156 }
2124 return bindings; 2157 return bindings;
2125 } 2158 }
2126 2159
2127 private CodeTree[] createTypeCheckCastAndCaches(SpecializationData specialization, List<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues, 2160 private CodeTree[] createTypeCheckAndLocals(SpecializationData specialization, List<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues,
2128 SpecializationExecution specializationExecution) { 2161 SpecializationExecution specializationExecution) {
2129 CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder(); 2162 CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder();
2130 CodeTreeBuilder castsAndCaches = CodeTreeBuilder.createBuilder(); 2163 CodeTreeBuilder localsBuilder = CodeTreeBuilder.createBuilder();
2131 for (TypeGuard typeGuard : typeGuards) { 2164 for (TypeGuard typeGuard : typeGuards) {
2132 int signatureIndex = typeGuard.getSignatureIndex(); 2165 int signatureIndex = typeGuard.getSignatureIndex();
2133 LocalVariable value = currentValues.getValue(signatureIndex); 2166 LocalVariable value = currentValues.getValue(signatureIndex);
2134 TypeData targetType = typeGuard.getType(); 2167 TypeData targetType = typeGuard.getType();
2135 if (!value.getType().needsCastTo(targetType)) { 2168 if (!value.getType().needsCastTo(targetType)) {
2186 } 2219 }
2187 2220
2188 if (castGuards == null || castGuards.contains(typeGuard)) { 2221 if (castGuards == null || castGuards.contains(typeGuard)) {
2189 LocalVariable castVariable = currentValues.getValue(execution).nextName().newType(typeGuard.getType()).accessWith(null); 2222 LocalVariable castVariable = currentValues.getValue(execution).nextName().newType(typeGuard.getType()).accessWith(null);
2190 currentValues.setValue(execution, castVariable); 2223 currentValues.setValue(execution, castVariable);
2191 castsAndCaches.tree(castVariable.createDeclaration(castBuilder.build())); 2224 localsBuilder.tree(castVariable.createDeclaration(castBuilder.build()));
2192 } 2225 }
2193 2226
2194 checksBuilder.tree(checkBuilder.build()); 2227 checksBuilder.tree(checkBuilder.build());
2195 } 2228 }
2196 2229
2200 castBoundTypes(bindExpressionValues(cache.getExpression(), specialization, currentValues))); 2233 castBoundTypes(bindExpressionValues(cache.getExpression(), specialization, currentValues)));
2201 String name = cache.getParameter().getLocalName(); 2234 String name = cache.getParameter().getLocalName();
2202 // multiple specializations might use the same name 2235 // multiple specializations might use the same name
2203 String varName = name + specialization.getIndex(); 2236 String varName = name + specialization.getIndex();
2204 TypeMirror type = cache.getParameter().getType(); 2237 TypeMirror type = cache.getParameter().getType();
2205 castsAndCaches.declaration(type, varName, initializer); 2238 localsBuilder.declaration(type, varName, initializer);
2206 currentValues.set(name, new LocalVariable(null, type, varName, null)); 2239 currentValues.set(name, new LocalVariable(null, type, varName, null));
2207 } 2240 }
2208 } 2241 }
2209 2242
2210 return new CodeTree[]{checksBuilder.build(), castsAndCaches.build()}; 2243 return new CodeTree[]{checksBuilder.build(), localsBuilder.build()};
2211 } 2244 }
2212 2245
2213 public static final class LocalContext { 2246 public static final class LocalContext {
2214 2247
2215 private final NodeGenFactory factory; 2248 private final NodeGenFactory factory;
2217 2250
2218 private LocalContext(NodeGenFactory factory) { 2251 private LocalContext(NodeGenFactory factory) {
2219 this.factory = factory; 2252 this.factory = factory;
2220 } 2253 }
2221 2254
2222 public void loadFastPathCachedValues(SpecializationData specialization) { 2255 public void loadFastPathState(SpecializationData specialization) {
2223 for (CacheExpression cache : specialization.getCaches()) { 2256 for (CacheExpression cache : specialization.getCaches()) {
2224 Parameter cacheParameter = cache.getParameter(); 2257 Parameter cacheParameter = cache.getParameter();
2225 String name = cacheParameter.getVariableElement().getSimpleName().toString(); 2258 String name = cacheParameter.getVariableElement().getSimpleName().toString();
2226 set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getTypeSystemType(), cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name))); 2259 set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getTypeSystemType(), cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name)));
2260 }
2261
2262 for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
2263 String name = assumptionName(assumption);
2264 TypeMirror type = assumption.getExpression().getResolvedType();
2265 set(name, new LocalVariable(null, type, name, CodeTreeBuilder.singleString("this." + name)));
2227 } 2266 }
2228 } 2267 }
2229 2268
2230 public CodeExecutableElement createMethod(Set<Modifier> modifiers, TypeMirror returnType, String name, String... optionalArguments) { 2269 public CodeExecutableElement createMethod(Set<Modifier> modifiers, TypeMirror returnType, String name, String... optionalArguments) {
2231 CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name); 2270 CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name);
2423 2462
2424 private LocalVariable getShortCircuit(NodeExecutionData execution) { 2463 private LocalVariable getShortCircuit(NodeExecutionData execution) {
2425 return values.get(shortCircuitName(execution)); 2464 return values.get(shortCircuitName(execution));
2426 } 2465 }
2427 2466
2467 @Override
2468 public String toString() {
2469 return "LocalContext [values=" + values + "]";
2470 }
2471
2428 } 2472 }
2429 2473
2430 public static final class LocalVariable { 2474 public static final class LocalVariable {
2431 2475
2432 private final TypeData type; 2476 private final TypeData type;