Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |