Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 13019003: Enable full type-checks in checked mode. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix a bug. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of ssa; 5 part of ssa;
6 6
7 /** 7 /**
8 * A special element for the extra parameter taken by intercepted 8 * A special element for the extra parameter taken by intercepted
9 * methods. We need to override [Element.computeType] because our 9 * methods. We need to override [Element.computeType] because our
10 * optimizers may look at its declared type. 10 * optimizers may look at its declared type.
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 352 }
353 353
354 /** 354 /**
355 * Returns an [HInstruction] for the given element. If the element is 355 * Returns an [HInstruction] for the given element. If the element is
356 * boxed or stored in a closure then the method generates code to retrieve 356 * boxed or stored in a closure then the method generates code to retrieve
357 * the value. 357 * the value.
358 */ 358 */
359 HInstruction readLocal(Element element) { 359 HInstruction readLocal(Element element) {
360 if (isAccessedDirectly(element)) { 360 if (isAccessedDirectly(element)) {
361 if (directLocals[element] == null) { 361 if (directLocals[element] == null) {
362 builder.compiler.internalError("Cannot find value $element", 362 if (element.isTypeVariable()) {
363 element: element); 363 builder.compiler.internalError(
364 "Runtime type information not available for $element",
365 element: builder.compiler.currentElement);
ngeoffray 2013/04/15 10:59:14 Thank you :)
366 } else {
367 builder.compiler.internalError(
368 "Cannot find value $element",
369 element: element);
370 }
364 } 371 }
365 return directLocals[element]; 372 return directLocals[element];
366 } else if (isStoredInClosureField(element)) { 373 } else if (isStoredInClosureField(element)) {
367 Element redirect = redirectionMapping[element]; 374 Element redirect = redirectionMapping[element];
368 HInstruction receiver = readLocal(closureData.closureElement); 375 HInstruction receiver = readLocal(closureData.closureElement);
369 HInstruction fieldGet = new HFieldGet(redirect, receiver); 376 HInstruction fieldGet = new HFieldGet(redirect, receiver);
370 fieldGet.instructionType = builder.getTypeOfCapturedVariable(element); 377 fieldGet.instructionType = builder.getTypeOfCapturedVariable(element);
371 builder.add(fieldGet); 378 builder.add(fieldGet);
372 return fieldGet; 379 return fieldGet;
373 } else if (isBoxed(element)) { 380 } else if (isBoxed(element)) {
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 return closeFunction(); 926 return closeFunction();
920 } 927 }
921 928
922 HGraph buildLazyInitializer(VariableElement variable) { 929 HGraph buildLazyInitializer(VariableElement variable) {
923 SendSet node = variable.parseNode(compiler); 930 SendSet node = variable.parseNode(compiler);
924 openFunction(variable, node); 931 openFunction(variable, node);
925 Link<Node> link = node.arguments; 932 Link<Node> link = node.arguments;
926 assert(!link.isEmpty && link.tail.isEmpty); 933 assert(!link.isEmpty && link.tail.isEmpty);
927 visit(link.head); 934 visit(link.head);
928 HInstruction value = pop(); 935 HInstruction value = pop();
929 value = potentiallyCheckType(value, variable.computeType(compiler)); 936 value = potentiallyCheckType(node, value, variable.computeType(compiler));
930 close(new HReturn(value)).addSuccessor(graph.exit); 937 close(new HReturn(value)).addSuccessor(graph.exit);
931 return closeFunction(); 938 return closeFunction();
932 } 939 }
933 940
934 /** 941 /**
935 * Returns the constructor body associated with the given constructor or 942 * Returns the constructor body associated with the given constructor or
936 * creates a new constructor body, if none can be found. 943 * creates a new constructor body, if none can be found.
937 * 944 *
938 * Returns [:null:] if the constructor does not have a body. 945 * Returns [:null:] if the constructor does not have a body.
939 */ 946 */
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 function, 1016 function,
1010 compiledArguments); 1017 compiledArguments);
1011 assert(succeeded); 1018 assert(succeeded);
1012 1019
1013 // Create the inlining state after evaluating the arguments, that 1020 // Create the inlining state after evaluating the arguments, that
1014 // may have an impact on the state of the current method. 1021 // may have an impact on the state of the current method.
1015 InliningState state = new InliningState( 1022 InliningState state = new InliningState(
1016 function, returnElement, returnType, elements, stack, localsHandler); 1023 function, returnElement, returnType, elements, stack, localsHandler);
1017 localsHandler = new LocalsHandler.from(localsHandler); 1024 localsHandler = new LocalsHandler.from(localsHandler);
1018 1025
1019 FunctionSignature signature = function.computeSignature(compiler);
1020 int index = 0;
1021 signature.orderedForEachParameter((Element parameter) {
1022 HInstruction argument = compiledArguments[index++];
1023 localsHandler.updateLocal(parameter, argument);
1024 potentiallyCheckType(argument, parameter.computeType(compiler));
1025 });
1026
1027 if (function.isConstructor()) { 1026 if (function.isConstructor()) {
1028 ClassElement enclosing = function.getEnclosingClass(); 1027 ClassElement enclosing = function.getEnclosingClass();
1029 if (backend.needsRti(enclosing)) { 1028 if (backend.needsRti(enclosing)) {
1030 assert(currentNode is NewExpression); 1029 assert(currentNode is NewExpression);
1031 InterfaceType type = elements.getType(currentNode); 1030 InterfaceType type = elements.getType(currentNode);
1032 Link<DartType> typeVariable = enclosing.typeVariables; 1031 Link<DartType> typeVariable = enclosing.typeVariables;
1033 type.typeArguments.forEach((DartType argument) { 1032 type.typeArguments.forEach((DartType argument) {
1034 HInstruction instruction = 1033 HInstruction instruction =
1035 analyzeTypeArgument(argument, currentNode); 1034 analyzeTypeArgument(argument, currentNode);
1036 localsHandler.updateLocal(typeVariable.head.element, instruction); 1035 localsHandler.updateLocal(typeVariable.head.element, instruction);
1037 typeVariable = typeVariable.tail; 1036 typeVariable = typeVariable.tail;
1038 }); 1037 });
1039 while (!typeVariable.isEmpty) { 1038 while (!typeVariable.isEmpty) {
1040 localsHandler.updateLocal(typeVariable.head.element, 1039 localsHandler.updateLocal(typeVariable.head.element,
1041 graph.addConstantNull(constantSystem)); 1040 graph.addConstantNull(constantSystem));
1042 typeVariable = typeVariable.tail; 1041 typeVariable = typeVariable.tail;
1043 } 1042 }
1044 } 1043 }
1045 } 1044 }
1046 1045
1046 FunctionSignature signature = function.computeSignature(compiler);
1047 int index = 0;
1048 signature.orderedForEachParameter((Element parameter) {
1049 HInstruction argument = compiledArguments[index++];
1050 localsHandler.updateLocal(parameter, argument);
1051 potentiallyCheckType(currentNode, argument,
1052 parameter.computeType(compiler));
1053 });
1054
1047 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. 1055 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here.
1048 returnElement = new ElementX(const SourceString("result"), 1056 returnElement = new ElementX(const SourceString("result"),
1049 ElementKind.VARIABLE, 1057 ElementKind.VARIABLE,
1050 function); 1058 function);
1051 localsHandler.updateLocal(returnElement, 1059 localsHandler.updateLocal(returnElement,
1052 graph.addConstantNull(constantSystem)); 1060 graph.addConstantNull(constantSystem));
1053 elements = compiler.enqueuer.resolution.getCachedElements(function); 1061 elements = compiler.enqueuer.resolution.getCachedElements(function);
1054 assert(elements != null); 1062 assert(elements != null);
1055 returnType = signature.returnType; 1063 returnType = signature.returnType;
1056 stack = <HInstruction>[]; 1064 stack = <HInstruction>[];
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1118 if (newElements == null) { 1126 if (newElements == null) {
1119 compiler.internalError("Element not resolved: $function"); 1127 compiler.internalError("Element not resolved: $function");
1120 } 1128 }
1121 1129
1122 if (canBeInlined == null) { 1130 if (canBeInlined == null) {
1123 canBeInlined = InlineWeeder.canBeInlined(functionExpression, newElements); 1131 canBeInlined = InlineWeeder.canBeInlined(functionExpression, newElements);
1124 backend.canBeInlined[function] = canBeInlined; 1132 backend.canBeInlined[function] = canBeInlined;
1125 if (!canBeInlined) return false; 1133 if (!canBeInlined) return false;
1126 } 1134 }
1127 1135
1136 // TODO(karlklose): remove this and enable inlining of these methods.
1137 if (compiler.enableTypeAssertions &&
1138 element.computeType(compiler).containsTypeVariables) {
1139 return false;
1140 }
1141
1128 assert(canBeInlined); 1142 assert(canBeInlined);
1129 InliningState state = enterInlinedMethod( 1143 InliningState state = enterInlinedMethod(
1130 function, selector, arguments, currentNode); 1144 function, selector, arguments, currentNode);
1131 inlinedFrom(element, () { 1145 inlinedFrom(element, () {
1132 functionExpression.body.accept(this); 1146 functionExpression.body.accept(this);
1133 }); 1147 });
1134 leaveInlinedMethod(state); 1148 leaveInlinedMethod(state);
1135 return true; 1149 return true;
1136 } 1150 }
1137 1151
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 1420
1407 // Analyze the constructor and all referenced constructors and collect 1421 // Analyze the constructor and all referenced constructors and collect
1408 // initializers and constructor bodies. 1422 // initializers and constructor bodies.
1409 List<FunctionElement> constructors = <FunctionElement>[functionElement]; 1423 List<FunctionElement> constructors = <FunctionElement>[functionElement];
1410 buildInitializers(functionElement, constructors, fieldValues); 1424 buildInitializers(functionElement, constructors, fieldValues);
1411 1425
1412 // Call the JavaScript constructor with the fields as argument. 1426 // Call the JavaScript constructor with the fields as argument.
1413 List<HInstruction> constructorArguments = <HInstruction>[]; 1427 List<HInstruction> constructorArguments = <HInstruction>[];
1414 classElement.forEachInstanceField( 1428 classElement.forEachInstanceField(
1415 (ClassElement enclosingClass, Element member) { 1429 (ClassElement enclosingClass, Element member) {
1416 constructorArguments.add(potentiallyCheckType( 1430 constructorArguments.add(potentiallyCheckType(function,
1417 fieldValues[member], member.computeType(compiler))); 1431 fieldValues[member], member.computeType(compiler)));
1418 }, 1432 },
1419 includeBackendMembers: true, 1433 includeBackendMembers: true,
1420 includeSuperMembers: true); 1434 includeSuperMembers: true);
1421 1435
1422 InterfaceType type = classElement.computeType(compiler); 1436 InterfaceType type = classElement.computeType(compiler);
1423 HType ssaType = new HType.nonNullExact(type, compiler); 1437 HType ssaType = new HType.nonNullExact(type, compiler);
1424 HForeignNew newObject = new HForeignNew(classElement, 1438 HForeignNew newObject = new HForeignNew(classElement,
1425 ssaType, 1439 ssaType,
1426 constructorArguments); 1440 constructorArguments);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 void openFunction(Element element, Expression node) { 1579 void openFunction(Element element, Expression node) {
1566 assert(invariant(element, element.isImplementation)); 1580 assert(invariant(element, element.isImplementation));
1567 HBasicBlock block = graph.addNewBlock(); 1581 HBasicBlock block = graph.addNewBlock();
1568 open(graph.entry); 1582 open(graph.entry);
1569 1583
1570 localsHandler.startFunction(element, node); 1584 localsHandler.startFunction(element, node);
1571 close(new HGoto()).addSuccessor(block); 1585 close(new HGoto()).addSuccessor(block);
1572 1586
1573 open(block); 1587 open(block);
1574 1588
1589 // Add the type parameters of the class as parameters of this method. This
1590 // must be done before adding the normal parameters, because their types
1591 // may contain references to type variables.
1592 var enclosing = element.enclosingElement;
1593 if ((element.isConstructor() || element.isGenerativeConstructorBody())
1594 && backend.needsRti(enclosing)) {
1595 enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
1596 HParameterValue param = addParameter(typeVariable.element);
1597 localsHandler.directLocals[typeVariable.element] = param;
1598 });
1599 }
1600
1575 if (element is FunctionElement) { 1601 if (element is FunctionElement) {
1576 FunctionElement functionElement = element; 1602 FunctionElement functionElement = element;
1577 FunctionSignature signature = functionElement.computeSignature(compiler); 1603 FunctionSignature signature = functionElement.computeSignature(compiler);
1578 signature.orderedForEachParameter((Element parameterElement) { 1604 signature.orderedForEachParameter((Element parameterElement) {
1579 if (elements.isParameterChecked(parameterElement)) { 1605 if (elements.isParameterChecked(parameterElement)) {
1580 addParameterCheckInstruction(parameterElement); 1606 addParameterCheckInstruction(parameterElement);
1581 } 1607 }
1582 }); 1608 });
1583 1609
1584 // Put the type checks in the first successor of the entry, 1610 // Put the type checks in the first successor of the entry,
1585 // because that is where the type guards will also be inserted. 1611 // because that is where the type guards will also be inserted.
1586 // This way we ensure that a type guard will dominate the type 1612 // This way we ensure that a type guard will dominate the type
1587 // check. 1613 // check.
1588 signature.orderedForEachParameter((Element parameterElement) { 1614 signature.orderedForEachParameter((Element parameterElement) {
1589 if (element.isGenerativeConstructorBody()) { 1615 if (element.isGenerativeConstructorBody()) {
1590 ClosureScope scopeData = 1616 ClosureScope scopeData =
1591 localsHandler.closureData.capturingScopes[node]; 1617 localsHandler.closureData.capturingScopes[node];
1592 if (scopeData != null 1618 if (scopeData != null
1593 && scopeData.capturedVariableMapping.containsKey( 1619 && scopeData.capturedVariableMapping.containsKey(
1594 parameterElement)) { 1620 parameterElement)) {
1595 // The parameter will be a field in the box passed as the 1621 // The parameter will be a field in the box passed as the
1596 // last parameter. So no need to have it. 1622 // last parameter. So no need to have it.
1597 return; 1623 return;
1598 } 1624 }
1599 } 1625 }
1600 HInstruction newParameter = potentiallyCheckType( 1626 HInstruction newParameter = potentiallyCheckType(
1627 node,
1601 localsHandler.directLocals[parameterElement], 1628 localsHandler.directLocals[parameterElement],
1602 parameterElement.computeType(compiler)); 1629 parameterElement.computeType(compiler));
1603 localsHandler.directLocals[parameterElement] = newParameter; 1630 localsHandler.directLocals[parameterElement] = newParameter;
1604 }); 1631 });
1605 1632
1606 returnType = signature.returnType; 1633 returnType = signature.returnType;
1607 } else { 1634 } else {
1608 // Otherwise it is a lazy initializer which does not have parameters. 1635 // Otherwise it is a lazy initializer which does not have parameters.
1609 assert(element is VariableElement); 1636 assert(element is VariableElement);
1610 } 1637 }
1611
1612 // Add the type parameters of the class as parameters of this
1613 // method.
1614 var enclosing = element.enclosingElement;
1615 if ((element.isConstructor() || element.isGenerativeConstructorBody())
1616 && backend.needsRti(enclosing)) {
1617 enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
1618 HParameterValue param = addParameter(typeVariable.element);
1619 localsHandler.directLocals[typeVariable.element] = param;
1620 });
1621 }
1622 } 1638 }
1623 1639
1624 HInstruction potentiallyCheckType( 1640 HInstruction potentiallyCheckType(
1625 HInstruction original, DartType type, 1641 Node node, HInstruction original, DartType type,
1626 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { 1642 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
1627 if (!compiler.enableTypeAssertions) return original; 1643 if (!compiler.enableTypeAssertions) return original;
1628 HInstruction other = original.convertType(compiler, type, kind); 1644 if (type.isDynamic || type.element == compiler.objectClass) {
1629 if (other != original) add(other); 1645 return original;
1630 return other; 1646 }
1647 if (kind == HTypeConversion.CHECKED_MODE_CHECK &&
1648 !type.isMalformed) {
1649 HInstruction checked =
1650 buildIsNode(node, type, original, checkedModeTest: true);
1651 add(checked);
1652 return checked;
1653 } else {
ngeoffray 2013/04/15 10:59:14 You should remove this else. A checked mode check
1654 HInstruction other = original.convertType(compiler, type, kind);
1655 if (other != original) add(other);
1656 return other;
1657 }
1631 } 1658 }
1632 1659
1633 HGraph closeFunction() { 1660 HGraph closeFunction() {
1634 // TODO(kasperl): Make this goto an implicit return. 1661 // TODO(kasperl): Make this goto an implicit return.
1635 if (!isAborted()) close(new HGoto()).addSuccessor(graph.exit); 1662 if (!isAborted()) close(new HGoto()).addSuccessor(graph.exit);
1636 graph.finalize(); 1663 graph.finalize();
1637 return graph; 1664 return graph;
1638 } 1665 }
1639 1666
1640 HBasicBlock addNewBlock() { 1667 HBasicBlock addNewBlock() {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1695 } 1722 }
1696 1723
1697 HInstruction pop() { 1724 HInstruction pop() {
1698 return stack.removeLast(); 1725 return stack.removeLast();
1699 } 1726 }
1700 1727
1701 void dup() { 1728 void dup() {
1702 stack.add(stack.last); 1729 stack.add(stack.last);
1703 } 1730 }
1704 1731
1705 HInstruction popBoolified() { 1732 HInstruction popBoolified(Node node) {
1706 HInstruction value = pop(); 1733 HInstruction value = pop();
1707 if (compiler.enableTypeAssertions) { 1734 if (compiler.enableTypeAssertions) {
1708 return potentiallyCheckType( 1735 return potentiallyCheckType(
1736 node,
1709 value, 1737 value,
1710 compiler.boolClass.computeType(compiler), 1738 compiler.boolClass.computeType(compiler),
1711 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 1739 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
1712 } 1740 }
1713 HInstruction result = new HBoolify(value); 1741 HInstruction result = new HBoolify(value);
1714 add(result); 1742 add(result);
1715 return result; 1743 return result;
1716 } 1744 }
1717 1745
1718 HInstruction attachPosition(HInstruction target, Node node) { 1746 HInstruction attachPosition(HInstruction target, Node node) {
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
2056 if (initializer.asExpression() != null) { 2084 if (initializer.asExpression() != null) {
2057 pop(); 2085 pop();
2058 } 2086 }
2059 } 2087 }
2060 } 2088 }
2061 HInstruction buildCondition() { 2089 HInstruction buildCondition() {
2062 if (node.condition == null) { 2090 if (node.condition == null) {
2063 return graph.addConstantBool(true, constantSystem); 2091 return graph.addConstantBool(true, constantSystem);
2064 } 2092 }
2065 visit(node.condition); 2093 visit(node.condition);
2066 return popBoolified(); 2094 return popBoolified(node);
2067 } 2095 }
2068 void buildUpdate() { 2096 void buildUpdate() {
2069 for (Expression expression in node.update) { 2097 for (Expression expression in node.update) {
2070 visit(expression); 2098 visit(expression);
2071 assert(!isAborted()); 2099 assert(!isAborted());
2072 // The result of the update instruction isn't used, and can just 2100 // The result of the update instruction isn't used, and can just
2073 // be dropped. 2101 // be dropped.
2074 HInstruction updateInstruction = pop(); 2102 HInstruction updateInstruction = pop();
2075 } 2103 }
2076 } 2104 }
2077 void buildBody() { 2105 void buildBody() {
2078 visit(node.body); 2106 visit(node.body);
2079 } 2107 }
2080 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); 2108 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
2081 } 2109 }
2082 2110
2083 visitWhile(While node) { 2111 visitWhile(While node) {
2084 HInstruction buildCondition() { 2112 HInstruction buildCondition() {
2085 visit(node.condition); 2113 visit(node.condition);
2086 return popBoolified(); 2114 return popBoolified(node);
2087 } 2115 }
2088 handleLoop(node, 2116 handleLoop(node,
2089 () {}, 2117 () {},
2090 buildCondition, 2118 buildCondition,
2091 () {}, 2119 () {},
2092 () { visit(node.body); }); 2120 () { visit(node.body); });
2093 } 2121 }
2094 2122
2095 visitDoWhile(DoWhile node) { 2123 visitDoWhile(DoWhile node) {
2096 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2124 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2156 } else { 2184 } else {
2157 info = new HLabeledBlockInformation.implicit(bodyInfo, target, 2185 info = new HLabeledBlockInformation.implicit(bodyInfo, target,
2158 isContinue: true); 2186 isContinue: true);
2159 } 2187 }
2160 bodyEntryBlock.setBlockFlow(info, conditionBlock); 2188 bodyEntryBlock.setBlockFlow(info, conditionBlock);
2161 } 2189 }
2162 open(conditionBlock); 2190 open(conditionBlock);
2163 2191
2164 visit(node.condition); 2192 visit(node.condition);
2165 assert(!isAborted()); 2193 assert(!isAborted());
2166 HInstruction conditionInstruction = popBoolified(); 2194 HInstruction conditionInstruction = popBoolified(node);
2167 HBasicBlock conditionEndBlock = close( 2195 HBasicBlock conditionEndBlock = close(
2168 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); 2196 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
2169 2197
2170 HBasicBlock avoidCriticalEdge = addNewBlock(); 2198 HBasicBlock avoidCriticalEdge = addNewBlock();
2171 conditionEndBlock.addSuccessor(avoidCriticalEdge); 2199 conditionEndBlock.addSuccessor(avoidCriticalEdge);
2172 open(avoidCriticalEdge); 2200 open(avoidCriticalEdge);
2173 close(new HGoto()); 2201 close(new HGoto());
2174 avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge. 2202 avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge.
2175 2203
2176 conditionExpression = 2204 conditionExpression =
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2271 visitIf(If node) { 2299 visitIf(If node) {
2272 handleIf(node, 2300 handleIf(node,
2273 () => visit(node.condition), 2301 () => visit(node.condition),
2274 () => visit(node.thenPart), 2302 () => visit(node.thenPart),
2275 node.elsePart != null ? () => visit(node.elsePart) : null); 2303 node.elsePart != null ? () => visit(node.elsePart) : null);
2276 } 2304 }
2277 2305
2278 void handleIf(Node diagnosticNode, 2306 void handleIf(Node diagnosticNode,
2279 void visitCondition(), void visitThen(), void visitElse()) { 2307 void visitCondition(), void visitThen(), void visitElse()) {
2280 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); 2308 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode);
2281 branchBuilder.handleIf(visitCondition, visitThen, visitElse); 2309 branchBuilder.handleIf(diagnosticNode, visitCondition, visitThen,
2310 visitElse);
2282 } 2311 }
2283 2312
2284 void visitLogicalAndOr(Send node, Operator op) { 2313 void visitLogicalAndOr(Send node, Operator op) {
2285 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); 2314 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node);
2286 branchBuilder.handleLogicalAndOrWithLeftNode( 2315 branchBuilder.handleLogicalAndOrWithLeftNode(
2316 node,
2287 node.receiver, 2317 node.receiver,
2288 () { visit(node.argumentsNode); }, 2318 () { visit(node.argumentsNode); },
2289 isAnd: (const SourceString("&&") == op.source)); 2319 isAnd: (const SourceString("&&") == op.source));
2290 } 2320 }
2291 2321
2292 void visitLogicalNot(Send node) { 2322 void visitLogicalNot(Send node) {
2293 assert(node.argumentsNode is Prefix); 2323 assert(node.argumentsNode is Prefix);
2294 visit(node.receiver); 2324 visit(node.receiver);
2295 HNot not = new HNot(popBoolified()); 2325 HNot not = new HNot(popBoolified(node));
2296 pushWithPosition(not, node); 2326 pushWithPosition(not, node);
2297 } 2327 }
2298 2328
2299 void visitUnary(Send node, Operator op) { 2329 void visitUnary(Send node, Operator op) {
2300 if (node.isParameterCheck) { 2330 if (node.isParameterCheck) {
2301 Element element = elements[node.receiver]; 2331 Element element = elements[node.receiver];
2302 Node function = element.enclosingElement.parseNode(compiler); 2332 Node function = element.enclosingElement.parseNode(compiler);
2303 ClosureClassMap parameterClosureData = 2333 ClosureClassMap parameterClosureData =
2304 compiler.closureToClassMapper.getMappingForNestedFunction(function); 2334 compiler.closureToClassMapper.getMappingForNestedFunction(function);
2305 Element fieldCheck = 2335 Element fieldCheck =
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2341 HIdentity eq = new HIdentity(left, right); 2371 HIdentity eq = new HIdentity(left, right);
2342 add(eq); 2372 add(eq);
2343 pushWithPosition(new HNot(eq), op); 2373 pushWithPosition(new HNot(eq), op);
2344 return; 2374 return;
2345 } 2375 }
2346 2376
2347 pushWithPosition( 2377 pushWithPosition(
2348 buildInvokeDynamic(send, selector, left, [right]), 2378 buildInvokeDynamic(send, selector, left, [right]),
2349 op); 2379 op);
2350 if (op.source.stringValue == '!=') { 2380 if (op.source.stringValue == '!=') {
2351 pushWithPosition(new HNot(popBoolified()), op); 2381 pushWithPosition(new HNot(popBoolified(send)), op);
2352 } 2382 }
2353 } 2383 }
2354 2384
2355 HInstruction generateInstanceSendReceiver(Send send) { 2385 HInstruction generateInstanceSendReceiver(Send send) {
2356 assert(Elements.isInstanceSend(send, elements)); 2386 assert(Elements.isInstanceSend(send, elements));
2357 if (send.receiver == null) { 2387 if (send.receiver == null) {
2358 return localsHandler.readThis(); 2388 return localsHandler.readThis();
2359 } 2389 }
2360 visit(send.receiver); 2390 visit(send.receiver);
2361 return pop(); 2391 return pop();
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2483 HInstruction value) { 2513 HInstruction value) {
2484 assert(!Elements.isInstanceSend(send, elements)); 2514 assert(!Elements.isInstanceSend(send, elements));
2485 if (Elements.isStaticOrTopLevelField(element)) { 2515 if (Elements.isStaticOrTopLevelField(element)) {
2486 if (element.isSetter()) { 2516 if (element.isSetter()) {
2487 HStatic target = new HStatic(element); 2517 HStatic target = new HStatic(element);
2488 add(target); 2518 add(target);
2489 addWithPosition( 2519 addWithPosition(
2490 new HInvokeStatic(<HInstruction>[target, value], HType.UNKNOWN), 2520 new HInvokeStatic(<HInstruction>[target, value], HType.UNKNOWN),
2491 send); 2521 send);
2492 } else { 2522 } else {
2493 value = potentiallyCheckType(value, element.computeType(compiler)); 2523 value =
2524 potentiallyCheckType(send, value, element.computeType(compiler));
2494 addWithPosition(new HStaticStore(element, value), send); 2525 addWithPosition(new HStaticStore(element, value), send);
2495 } 2526 }
2496 stack.add(value); 2527 stack.add(value);
2497 } else if (Elements.isErroneousElement(element)) { 2528 } else if (Elements.isErroneousElement(element)) {
2498 // An erroneous element indicates an unresolved static setter. 2529 // An erroneous element indicates an unresolved static setter.
2499 generateThrowNoSuchMethod(send, 2530 generateThrowNoSuchMethod(send,
2500 getTargetName(element, 'set'), 2531 getTargetName(element, 'set'),
2501 argumentNodes: send.arguments); 2532 argumentNodes: send.arguments);
2502 } else { 2533 } else {
2503 stack.add(value); 2534 stack.add(value);
2504 // If the value does not already have a name, give it here. 2535 // If the value does not already have a name, give it here.
2505 if (value.sourceElement == null) { 2536 if (value.sourceElement == null) {
2506 value.sourceElement = element; 2537 value.sourceElement = element;
2507 } 2538 }
2508 HInstruction checked = potentiallyCheckType( 2539 HInstruction checked =
2509 value, element.computeType(compiler)); 2540 potentiallyCheckType(send, value, element.computeType(compiler));
2510 if (!identical(checked, value)) { 2541 if (!identical(checked, value)) {
2511 pop(); 2542 pop();
2512 stack.add(checked); 2543 stack.add(checked);
2513 } 2544 }
2514 localsHandler.updateLocal(element, checked); 2545 localsHandler.updateLocal(element, checked);
2515 } 2546 }
2516 } 2547 }
2517 2548
2518 HInstruction invokeInterceptor(Set<ClassElement> intercepted, 2549 HInstruction invokeInterceptor(Set<ClassElement> intercepted,
2519 HInstruction receiver, 2550 HInstruction receiver,
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
2675 isNot = true; 2706 isNot = true;
2676 } 2707 }
2677 DartType type = elements.getType(typeAnnotation); 2708 DartType type = elements.getType(typeAnnotation);
2678 if (type.isMalformed) { 2709 if (type.isMalformed) {
2679 String reasons = Types.fetchReasonsFromMalformedType(type); 2710 String reasons = Types.fetchReasonsFromMalformedType(type);
2680 if (compiler.enableTypeAssertions) { 2711 if (compiler.enableTypeAssertions) {
2681 generateMalformedSubtypeError(node, expression, type, reasons); 2712 generateMalformedSubtypeError(node, expression, type, reasons);
2682 } else { 2713 } else {
2683 generateRuntimeError(node, '$type is malformed: $reasons'); 2714 generateRuntimeError(node, '$type is malformed: $reasons');
2684 } 2715 }
2685 return; 2716 } else {
2717 HInstruction instruction = buildIsNode(node, type, expression);
2718 if (isNot) {
2719 add(instruction);
2720 instruction = new HNot(instruction);
2721 }
2722 push(instruction);
2686 } 2723 }
2724 }
2687 2725
2688 HInstruction instruction; 2726 HInstruction buildIsNode(Node node, DartType type, HInstruction expression,
2727 {bool checkedModeTest: false}) {
ngeoffray 2013/04/15 10:59:14 I'd prefer if the call sites always added the name
2728 HType returnType =
2729 checkedModeTest ? expression.instructionType : HType.BOOLEAN;
2689 if (type.kind == TypeKind.TYPE_VARIABLE) { 2730 if (type.kind == TypeKind.TYPE_VARIABLE) {
2690 HInstruction runtimeType = addTypeVariableReference(type); 2731 HInstruction runtimeType = addTypeVariableReference(type);
2691 Element helper = backend.getGetObjectIsSubtype(); 2732 Element helper = checkedModeTest ? backend.getAssertObjectIsSubtype()
2733 : backend.getObjectIsSubtype();
2692 HInstruction helperCall = new HStatic(helper); 2734 HInstruction helperCall = new HStatic(helper);
2693 add(helperCall); 2735 add(helperCall);
2694 List<HInstruction> inputs = <HInstruction>[helperCall, expression, 2736 List<HInstruction> inputs = <HInstruction>[helperCall, expression,
2695 runtimeType]; 2737 runtimeType];
2696 HInstruction call = new HInvokeStatic(inputs, HType.BOOLEAN); 2738 HInstruction call = new HInvokeStatic(inputs, returnType);
2697 add(call); 2739 add(call);
2698 instruction = new HIs(type, <HInstruction>[expression, call], 2740 return new HIs(type, <HInstruction>[expression, call],
2699 HIs.VARIABLE_CHECK); 2741 HIs.VARIABLE_CHECK, checkedModeTest, returnType);
2700 } else if (RuntimeTypes.hasTypeArguments(type)) { 2742 } else if (RuntimeTypes.hasTypeArguments(type)) {
2701 Element element = type.element; 2743 Element element = type.element;
2702 bool needsNativeCheck = 2744 bool needsNativeCheck =
2703 backend.emitter.nativeEmitter.requiresNativeIsCheck(element); 2745 backend.emitter.nativeEmitter.requiresNativeIsCheck(element);
2704 Element helper = backend.getCheckSubtype(); 2746 Element helper = checkedModeTest ? backend.getAssertSubtype()
2747 : backend.getCheckSubtype();
2705 HInstruction helperCall = new HStatic(helper); 2748 HInstruction helperCall = new HStatic(helper);
2706 add(helperCall); 2749 add(helperCall);
2707 HInstruction representations = 2750 HInstruction representations =
2708 buildTypeArgumentRepresentations(type); 2751 buildTypeArgumentRepresentations(type);
2709 add(representations); 2752 add(representations);
2710 HInstruction isFieldName = 2753 HInstruction isFieldName =
2711 addConstantString(node, backend.namer.operatorIs(element)); 2754 addConstantString(node, backend.namer.operatorIs(element));
2712 // TODO(karlklose): use [:null:] for [asField] if [element] does not 2755 // TODO(karlklose): use [:null:] for [asField] if [element] does not
2713 // have a subclass. 2756 // have a subclass.
2714 HInstruction asFieldName = 2757 HInstruction asFieldName =
2715 addConstantString(node, backend.namer.substitutionName(element)); 2758 addConstantString(node, backend.namer.substitutionName(element));
2716 HInstruction native = 2759 HInstruction native =
2717 graph.addConstantBool(needsNativeCheck, constantSystem); 2760 graph.addConstantBool(needsNativeCheck, constantSystem);
2718 List<HInstruction> inputs = <HInstruction>[helperCall, 2761 List<HInstruction> inputs = <HInstruction>[helperCall,
2719 expression, 2762 expression,
2720 isFieldName, 2763 isFieldName,
2721 representations, 2764 representations,
2722 asFieldName, 2765 asFieldName,
2723 native]; 2766 native];
2724 HInstruction call = new HInvokeStatic(inputs, HType.BOOLEAN); 2767 HInstruction call = new HInvokeStatic(inputs, returnType);
2725 add(call); 2768 add(call);
2726 instruction = new HIs(type, <HInstruction>[expression, call], 2769 return new HIs(type, <HInstruction>[expression, call],
2727 HIs.COMPOUND_CHECK); 2770 HIs.COMPOUND_CHECK, checkedModeTest, returnType);
2771 } else if (checkedModeTest) {
2772 FunctionElement helper = backend.getCheckedModeHelper(type);
2773 HInstruction helperCall = new HStatic(helper);
2774 add(helperCall);
2775 List<HInstruction> inputs = <HInstruction>[helperCall, expression];
2776 if (helper.functionSignature.requiredParameterCount == 2) {
2777 // 2 arguments implies that the method is either [propertyTypeCheck]
2778 // or [propertyTypeCast].
2779 String isFieldName = backend.namer.operatorIs(type.element);
2780 inputs.add(addConstantString(node, isFieldName));
2781 }
2782 HInstruction call = new HInvokeStatic(inputs, returnType);
2783 add(call);
2784 return new HIs(type, <HInstruction>[expression, call], HIs.RAW_ASSERT,
2785 checkedModeTest, returnType);
2728 } else { 2786 } else {
2729 instruction = new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK); 2787 assert(!checkedModeTest);
2788 return new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK, false,
2789 returnType);
2730 } 2790 }
2731 if (isNot) {
2732 add(instruction);
2733 instruction = new HNot(instruction);
2734 }
2735 push(instruction);
2736 } 2791 }
2737 2792
2738 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { 2793 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) {
2739 Selector selector = elements.getSelector(node); 2794 Selector selector = elements.getSelector(node);
2740 if (selector.namedArgumentCount == 0) { 2795 if (selector.namedArgumentCount == 0) {
2741 addGenericSendArgumentsToList(node.arguments, list); 2796 addGenericSendArgumentsToList(node.arguments, list);
2742 } else { 2797 } else {
2743 // Visit positional arguments and add them to the list. 2798 // Visit positional arguments and add them to the list.
2744 Link<Node> arguments = node.arguments; 2799 Link<Node> arguments = node.arguments;
2745 int positionalArgumentCount = selector.positionalArgumentCount; 2800 int positionalArgumentCount = selector.positionalArgumentCount;
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after
3872 native.handleSsaNative(this, node.expression); 3927 native.handleSsaNative(this, node.expression);
3873 return; 3928 return;
3874 } 3929 }
3875 assert(invariant(node, !node.isRedirectingFactoryBody)); 3930 assert(invariant(node, !node.isRedirectingFactoryBody));
3876 HInstruction value; 3931 HInstruction value;
3877 if (node.expression == null) { 3932 if (node.expression == null) {
3878 value = graph.addConstantNull(constantSystem); 3933 value = graph.addConstantNull(constantSystem);
3879 } else { 3934 } else {
3880 visit(node.expression); 3935 visit(node.expression);
3881 value = pop(); 3936 value = pop();
3882 value = potentiallyCheckType(value, returnType); 3937 value = potentiallyCheckType(node, value, returnType);
3883 } 3938 }
3884 3939
3885 handleInTryStatement(); 3940 handleInTryStatement();
3886 3941
3887 if (!inliningStack.isEmpty) { 3942 if (!inliningStack.isEmpty) {
3888 localsHandler.updateLocal(returnElement, value); 3943 localsHandler.updateLocal(returnElement, value);
3889 } else { 3944 } else {
3890 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); 3945 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit);
3891 } 3946 }
3892 } 3947 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3940 !link.isEmpty; 3995 !link.isEmpty;
3941 link = link.tail) { 3996 link = link.tail) {
3942 visit(link.head); 3997 visit(link.head);
3943 inputs.add(pop()); 3998 inputs.add(pop());
3944 } 3999 }
3945 push(new HLiteralList(inputs)); 4000 push(new HLiteralList(inputs));
3946 } 4001 }
3947 4002
3948 visitConditional(Conditional node) { 4003 visitConditional(Conditional node) {
3949 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 4004 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
3950 brancher.handleConditional(() => visit(node.condition), 4005 brancher.handleConditional(node,
4006 () => visit(node.condition),
3951 () => visit(node.thenExpression), 4007 () => visit(node.thenExpression),
3952 () => visit(node.elseExpression)); 4008 () => visit(node.elseExpression));
3953 } 4009 }
3954 4010
3955 visitStringInterpolation(StringInterpolation node) { 4011 visitStringInterpolation(StringInterpolation node) {
3956 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); 4012 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node);
3957 stringBuilder.visit(node); 4013 stringBuilder.visit(node);
3958 stack.add(stringBuilder.result); 4014 stack.add(stringBuilder.result);
3959 } 4015 }
3960 4016
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
4043 new HInvokeDynamicGetter(selector, null, interceptor, !hasGetter); 4099 new HInvokeDynamicGetter(selector, null, interceptor, !hasGetter);
4044 // Add the receiver as an argument to the getter call on the 4100 // Add the receiver as an argument to the getter call on the
4045 // interceptor. 4101 // interceptor.
4046 iterator.inputs.add(receiver); 4102 iterator.inputs.add(receiver);
4047 } 4103 }
4048 add(iterator); 4104 add(iterator);
4049 } 4105 }
4050 HInstruction buildCondition() { 4106 HInstruction buildCondition() {
4051 Selector selector = elements.getMoveNextSelector(node); 4107 Selector selector = elements.getMoveNextSelector(node);
4052 push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator])); 4108 push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator]));
4053 return popBoolified(); 4109 return popBoolified(node);
4054 } 4110 }
4055 void buildBody() { 4111 void buildBody() {
4056 Selector call = elements.getCurrentSelector(node); 4112 Selector call = elements.getCurrentSelector(node);
4057 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call); 4113 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call);
4058 push(new HInvokeDynamicGetter(call, null, iterator, !hasGetter)); 4114 push(new HInvokeDynamicGetter(call, null, iterator, !hasGetter));
4059 4115
4060 Element variable; 4116 Element variable;
4061 if (node.declaredIdentifier.asSend() != null) { 4117 if (node.declaredIdentifier.asSend() != null) {
4062 variable = elements[node.declaredIdentifier]; 4118 variable = elements[node.declaredIdentifier];
4063 } else { 4119 } else {
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
4479 if (tail.isEmpty) { 4535 if (tail.isEmpty) {
4480 left(); 4536 left();
4481 return; 4537 return;
4482 } 4538 }
4483 4539
4484 void right() { 4540 void right() {
4485 buildTests(tail); 4541 buildTests(tail);
4486 } 4542 }
4487 SsaBranchBuilder branchBuilder = 4543 SsaBranchBuilder branchBuilder =
4488 new SsaBranchBuilder(this, remainingCases.head); 4544 new SsaBranchBuilder(this, remainingCases.head);
4489 branchBuilder.handleLogicalAndOr(left, right, isAnd: false); 4545 branchBuilder.handleLogicalAndOr(remainingCases.head, left, right,
4546 isAnd: false);
4490 } 4547 }
4491 4548
4492 if (node.isDefaultCase) { 4549 if (node.isDefaultCase) {
4493 // Default case must be last. 4550 // Default case must be last.
4494 assert(cases.tail.isEmpty); 4551 assert(cases.tail.isEmpty);
4495 // Perform the tests until one of them match, but then always execute the 4552 // Perform the tests until one of them match, but then always execute the
4496 // statements. 4553 // statements.
4497 // TODO(lrn): Stop performing tests when all expressions are compile-time 4554 // TODO(lrn): Stop performing tests when all expressions are compile-time
4498 // constant strings or integers. 4555 // constant strings or integers.
4499 handleIf(node, () { buildTests(labelsAndCases); }, (){}, null); 4556 handleIf(node, () { buildTests(labelsAndCases); }, (){}, null);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
4580 } 4637 }
4581 if (type.isMalformed) { 4638 if (type.isMalformed) {
4582 // TODO(johnniwinther): Handle malformed types in [HIs] instead. 4639 // TODO(johnniwinther): Handle malformed types in [HIs] instead.
4583 HInstruction condition = 4640 HInstruction condition =
4584 graph.addConstantBool(true, constantSystem); 4641 graph.addConstantBool(true, constantSystem);
4585 stack.add(condition); 4642 stack.add(condition);
4586 } else { 4643 } else {
4587 // TODO(karlkose): support type arguments here. 4644 // TODO(karlkose): support type arguments here.
4588 HInstruction condition = new HIs(type, 4645 HInstruction condition = new HIs(type,
4589 <HInstruction>[unwrappedException], 4646 <HInstruction>[unwrappedException],
4590 HIs.RAW_CHECK); 4647 HIs.RAW_CHECK,
4648 false,
4649 HType.BOOLEAN);
4591 push(condition); 4650 push(condition);
4592 } 4651 }
4593 } else { 4652 } else {
4594 VariableDefinitions declaration = catchBlock.formals.nodes.head; 4653 VariableDefinitions declaration = catchBlock.formals.nodes.head;
4595 HInstruction condition = null; 4654 HInstruction condition = null;
4596 if (declaration.type == null) { 4655 if (declaration.type == null) {
4597 condition = graph.addConstantBool(true, constantSystem); 4656 condition = graph.addConstantBool(true, constantSystem);
4598 stack.add(condition); 4657 stack.add(condition);
4599 } else { 4658 } else {
4600 // TODO(aprelev@gmail.com): Once old catch syntax is removed 4659 // TODO(aprelev@gmail.com): Once old catch syntax is removed
4601 // "if" condition above and this "else" branch should be deleted as 4660 // "if" condition above and this "else" branch should be deleted as
4602 // type of declared variable won't matter for the catch 4661 // type of declared variable won't matter for the catch
4603 // condition. 4662 // condition.
4604 DartType type = elements.getType(declaration.type); 4663 DartType type = elements.getType(declaration.type);
4605 if (type == null) { 4664 if (type == null) {
4606 compiler.cancel('Catch with unresolved type', node: catchBlock); 4665 compiler.cancel('Catch with unresolved type', node: catchBlock);
4607 } 4666 }
4608 // TODO(karlkose): support type arguments here. 4667 // TODO(karlkose): support type arguments here.
4609 condition = new HIs(type, <HInstruction>[unwrappedException], 4668 condition = new HIs(type, <HInstruction>[unwrappedException],
4610 HIs.RAW_CHECK, nullOk: true); 4669 HIs.RAW_CHECK, false, HType.BOOLEAN,
4670 nullOk: true);
4611 push(condition); 4671 push(condition);
4612 } 4672 }
4613 } 4673 }
4614 } 4674 }
4615 4675
4616 void visitThen() { 4676 void visitThen() {
4617 CatchBlock catchBlock = link.head; 4677 CatchBlock catchBlock = link.head;
4618 link = link.tail; 4678 link = link.tail;
4619 4679
4620 if (compiler.enableTypeAssertions) { 4680 if (compiler.enableTypeAssertions) {
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
4951 SsaBranchBuilder(this.builder, [this.diagnosticNode]); 5011 SsaBranchBuilder(this.builder, [this.diagnosticNode]);
4952 5012
4953 Compiler get compiler => builder.compiler; 5013 Compiler get compiler => builder.compiler;
4954 5014
4955 void checkNotAborted() { 5015 void checkNotAborted() {
4956 if (builder.isAborted()) { 5016 if (builder.isAborted()) {
4957 compiler.unimplemented("aborted control flow", node: diagnosticNode); 5017 compiler.unimplemented("aborted control flow", node: diagnosticNode);
4958 } 5018 }
4959 } 5019 }
4960 5020
4961 void buildCondition(void visitCondition(), 5021 void buildCondition(Node node,
5022 void visitCondition(),
4962 SsaBranch conditionBranch, 5023 SsaBranch conditionBranch,
4963 SsaBranch thenBranch, 5024 SsaBranch thenBranch,
4964 SsaBranch elseBranch) { 5025 SsaBranch elseBranch) {
4965 startBranch(conditionBranch); 5026 startBranch(conditionBranch);
4966 visitCondition(); 5027 visitCondition();
4967 checkNotAborted(); 5028 checkNotAborted();
4968 assert(identical(builder.current, builder.lastOpenedBlock)); 5029 assert(identical(builder.current, builder.lastOpenedBlock));
4969 HInstruction conditionValue = builder.popBoolified(); 5030 HInstruction conditionValue = builder.popBoolified(node);
4970 HIf branch = new HIf(conditionValue); 5031 HIf branch = new HIf(conditionValue);
4971 HBasicBlock conditionExitBlock = builder.current; 5032 HBasicBlock conditionExitBlock = builder.current;
4972 builder.close(branch); 5033 builder.close(branch);
4973 conditionBranch.exitLocals = builder.localsHandler; 5034 conditionBranch.exitLocals = builder.localsHandler;
4974 conditionExitBlock.addSuccessor(thenBranch.block); 5035 conditionExitBlock.addSuccessor(thenBranch.block);
4975 conditionExitBlock.addSuccessor(elseBranch.block); 5036 conditionExitBlock.addSuccessor(elseBranch.block);
4976 bool conditionBranchLocalsCanBeReused = 5037 bool conditionBranchLocalsCanBeReused =
4977 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true); 5038 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true);
4978 mergeLocals(conditionBranch, elseBranch, 5039 mergeLocals(conditionBranch, elseBranch,
4979 mayReuseFromLocals: conditionBranchLocalsCanBeReused); 5040 mayReuseFromLocals: conditionBranchLocalsCanBeReused);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
5021 builder.goto(builder.current, joinBranch.block); 5082 builder.goto(builder.current, joinBranch.block);
5022 mergeLocals(branch, joinBranch, mayReuseFromLocals: true); 5083 mergeLocals(branch, joinBranch, mayReuseFromLocals: true);
5023 } 5084 }
5024 if (isExpression) { 5085 if (isExpression) {
5025 checkNotAborted(); 5086 checkNotAborted();
5026 return builder.pop(); 5087 return builder.pop();
5027 } 5088 }
5028 return null; 5089 return null;
5029 } 5090 }
5030 5091
5031 handleIf(void visitCondition(), void visitThen(), void visitElse()) { 5092 handleIf(Node node, void visitCondition(), void visitThen(),
5093 void visitElse()) {
5032 if (visitElse == null) { 5094 if (visitElse == null) {
5033 // Make sure to have an else part to avoid a critical edge. A 5095 // Make sure to have an else part to avoid a critical edge. A
5034 // critical edge is an edge that connects a block with multiple 5096 // critical edge is an edge that connects a block with multiple
5035 // successors to a block with multiple predecessors. We avoid 5097 // successors to a block with multiple predecessors. We avoid
5036 // such edges because they prevent inserting copies during code 5098 // such edges because they prevent inserting copies during code
5037 // generation of phi instructions. 5099 // generation of phi instructions.
5038 visitElse = () {}; 5100 visitElse = () {};
5039 } 5101 }
5040 5102
5041 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); 5103 _handleDiamondBranch(node, visitCondition, visitThen, visitElse, false);
5042 } 5104 }
5043 5105
5044 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { 5106 handleConditional(Node node, void visitCondition(), void visitThen(),
5107 void visitElse()) {
5045 assert(visitElse != null); 5108 assert(visitElse != null);
5046 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); 5109 _handleDiamondBranch(node, visitCondition, visitThen, visitElse, true);
5047 } 5110 }
5048 5111
5049 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) { 5112 void handleLogicalAndOr(Node node, void left(), void right(), {bool isAnd}) {
5050 // x && y is transformed into: 5113 // x && y is transformed into:
5051 // t0 = boolify(x); 5114 // t0 = boolify(x);
5052 // if (t0) { 5115 // if (t0) {
5053 // t1 = boolify(y); 5116 // t1 = boolify(y);
5054 // } 5117 // }
5055 // result = phi(t1, false); 5118 // result = phi(t1, false);
5056 // 5119 //
5057 // x || y is transformed into: 5120 // x || y is transformed into:
5058 // t0 = boolify(x); 5121 // t0 = boolify(x);
5059 // if (not(t0)) { 5122 // if (not(t0)) {
5060 // t1 = boolify(y); 5123 // t1 = boolify(y);
5061 // } 5124 // }
5062 // result = phi(t1, true); 5125 // result = phi(t1, true);
5063 HInstruction boolifiedLeft; 5126 HInstruction boolifiedLeft;
5064 HInstruction boolifiedRight; 5127 HInstruction boolifiedRight;
5065 5128
5066 void visitCondition() { 5129 void visitCondition() {
5067 left(); 5130 left();
5068 boolifiedLeft = builder.popBoolified(); 5131 boolifiedLeft = builder.popBoolified(node);
5069 builder.stack.add(boolifiedLeft); 5132 builder.stack.add(boolifiedLeft);
5070 if (!isAnd) { 5133 if (!isAnd) {
5071 builder.push(new HNot(builder.pop())); 5134 builder.push(new HNot(builder.pop()));
5072 } 5135 }
5073 } 5136 }
5074 5137
5075 void visitThen() { 5138 void visitThen() {
5076 right(); 5139 right();
5077 boolifiedRight = builder.popBoolified(); 5140 boolifiedRight = builder.popBoolified(node);
5078 } 5141 }
5079 5142
5080 handleIf(visitCondition, visitThen, null); 5143 handleIf(node, visitCondition, visitThen, null);
5081 HConstant notIsAnd = 5144 HConstant notIsAnd =
5082 builder.graph.addConstantBool(!isAnd, builder.constantSystem); 5145 builder.graph.addConstantBool(!isAnd, builder.constantSystem);
5083 HPhi result = new HPhi.manyInputs(null, 5146 HPhi result = new HPhi.manyInputs(null,
5084 <HInstruction>[boolifiedRight, notIsAnd]); 5147 <HInstruction>[boolifiedRight, notIsAnd]);
5085 builder.current.addPhi(result); 5148 builder.current.addPhi(result);
5086 builder.stack.add(result); 5149 builder.stack.add(result);
5087 } 5150 }
5088 5151
5089 void handleLogicalAndOrWithLeftNode(Node left, 5152 void handleLogicalAndOrWithLeftNode(Node node,
5153 Node left,
5090 void visitRight(), 5154 void visitRight(),
5091 {bool isAnd}) { 5155 {bool isAnd}) {
5092 // This method is similar to [handleLogicalAndOr] but optimizes the case 5156 // This method is similar to [handleLogicalAndOr] but optimizes the case
5093 // where left is a logical "and" or logical "or". 5157 // where left is a logical "and" or logical "or".
5094 // 5158 //
5095 // For example (x && y) && z is transformed into x && (y && z): 5159 // For example (x && y) && z is transformed into x && (y && z):
5096 // t0 = boolify(x); 5160 // t0 = boolify(x);
5097 // if (t0) { 5161 // if (t0) {
5098 // t1 = boolify(y); 5162 // t1 = boolify(y);
5099 // if (t1) { 5163 // if (t1) {
5100 // t2 = boolify(z); 5164 // t2 = boolify(z);
5101 // } 5165 // }
5102 // t3 = phi(t2, false); 5166 // t3 = phi(t2, false);
5103 // } 5167 // }
5104 // result = phi(t3, false); 5168 // result = phi(t3, false);
5105 5169
5106 Send send = left.asSend(); 5170 Send send = left.asSend();
5107 if (send != null && 5171 if (send != null &&
5108 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) { 5172 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) {
5109 Node newLeft = send.receiver; 5173 Node newLeft = send.receiver;
5110 Link<Node> link = send.argumentsNode.nodes; 5174 Link<Node> link = send.argumentsNode.nodes;
5111 assert(link.tail.isEmpty); 5175 assert(link.tail.isEmpty);
5112 Node middle = link.head; 5176 Node middle = link.head;
5113 handleLogicalAndOrWithLeftNode( 5177 handleLogicalAndOrWithLeftNode(
5178 node,
5114 newLeft, 5179 newLeft,
5115 () => handleLogicalAndOrWithLeftNode(middle, visitRight, 5180 () => handleLogicalAndOrWithLeftNode(node, middle, visitRight,
5116 isAnd: isAnd), 5181 isAnd: isAnd),
5117 isAnd: isAnd); 5182 isAnd: isAnd);
5118 } else { 5183 } else {
5119 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); 5184 handleLogicalAndOr(node, () => builder.visit(left), visitRight,
5185 isAnd: isAnd);
5120 } 5186 }
5121 } 5187 }
5122 5188
5123 void _handleDiamondBranch(void visitCondition(), 5189 void _handleDiamondBranch(Node node,
5190 void visitCondition(),
5124 void visitThen(), 5191 void visitThen(),
5125 void visitElse(), 5192 void visitElse(),
5126 bool isExpression) { 5193 bool isExpression) {
5127 SsaBranch conditionBranch = new SsaBranch(this); 5194 SsaBranch conditionBranch = new SsaBranch(this);
5128 SsaBranch thenBranch = new SsaBranch(this); 5195 SsaBranch thenBranch = new SsaBranch(this);
5129 SsaBranch elseBranch = new SsaBranch(this); 5196 SsaBranch elseBranch = new SsaBranch(this);
5130 SsaBranch joinBranch = new SsaBranch(this); 5197 SsaBranch joinBranch = new SsaBranch(this);
5131 5198
5132 conditionBranch.startLocals = builder.localsHandler; 5199 conditionBranch.startLocals = builder.localsHandler;
5133 builder.goto(builder.current, conditionBranch.block); 5200 builder.goto(builder.current, conditionBranch.block);
5134 5201
5135 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch); 5202 buildCondition(node, visitCondition, conditionBranch, thenBranch,
5203 elseBranch);
5136 HInstruction thenValue = 5204 HInstruction thenValue =
5137 buildBranch(thenBranch, visitThen, joinBranch, isExpression); 5205 buildBranch(thenBranch, visitThen, joinBranch, isExpression);
5138 HInstruction elseValue = 5206 HInstruction elseValue =
5139 buildBranch(elseBranch, visitElse, joinBranch, isExpression); 5207 buildBranch(elseBranch, visitElse, joinBranch, isExpression);
5140 5208
5141 if (isExpression) { 5209 if (isExpression) {
5142 assert(thenValue != null && elseValue != null); 5210 assert(thenValue != null && elseValue != null);
5143 HPhi phi = 5211 HPhi phi =
5144 new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue]); 5212 new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue]);
5145 joinBranch.block.addPhi(phi); 5213 joinBranch.block.addPhi(phi);
(...skipping 16 matching lines...) Expand all
5162 new HSubGraphBlockInformation(elseBranch.graph)); 5230 new HSubGraphBlockInformation(elseBranch.graph));
5163 5231
5164 HBasicBlock conditionStartBlock = conditionBranch.block; 5232 HBasicBlock conditionStartBlock = conditionBranch.block;
5165 conditionStartBlock.setBlockFlow(info, joinBlock); 5233 conditionStartBlock.setBlockFlow(info, joinBlock);
5166 SubGraph conditionGraph = conditionBranch.graph; 5234 SubGraph conditionGraph = conditionBranch.graph;
5167 HIf branch = conditionGraph.end.last; 5235 HIf branch = conditionGraph.end.last;
5168 assert(branch is HIf); 5236 assert(branch is HIf);
5169 branch.blockInformation = conditionStartBlock.blockFlow; 5237 branch.blockInformation = conditionStartBlock.blockFlow;
5170 } 5238 }
5171 } 5239 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698