| 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 class Interceptors { | 5 class Interceptors { |
| 6 Compiler compiler; | 6 Compiler compiler; |
| 7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
| 8 | 8 |
| 9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
| 10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
| (...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 assert(elements[function] != null); | 941 assert(elements[function] != null); |
| 942 openFunction(functionElement, function); | 942 openFunction(functionElement, function); |
| 943 function.body.accept(this); | 943 function.body.accept(this); |
| 944 return closeFunction(); | 944 return closeFunction(); |
| 945 } | 945 } |
| 946 | 946 |
| 947 HGraph buildLazyInitializer(VariableElement variable) { | 947 HGraph buildLazyInitializer(VariableElement variable) { |
| 948 SendSet node = variable.parseNode(compiler); | 948 SendSet node = variable.parseNode(compiler); |
| 949 openFunction(variable, node); | 949 openFunction(variable, node); |
| 950 Link<Node> link = node.arguments; | 950 Link<Node> link = node.arguments; |
| 951 assert(!link.isEmpty() && link.tail.isEmpty()); | 951 assert(!link.isEmpty && link.tail.isEmpty); |
| 952 visit(link.head); | 952 visit(link.head); |
| 953 HInstruction value = pop(); | 953 HInstruction value = pop(); |
| 954 value = potentiallyCheckType(value, variable); | 954 value = potentiallyCheckType(value, variable); |
| 955 close(new HReturn(value)).addSuccessor(graph.exit); | 955 close(new HReturn(value)).addSuccessor(graph.exit); |
| 956 return closeFunction(); | 956 return closeFunction(); |
| 957 } | 957 } |
| 958 | 958 |
| 959 /** | 959 /** |
| 960 * Returns the constructor body associated with the given constructor or | 960 * Returns the constructor body associated with the given constructor or |
| 961 * creates a new constructor body, if none can be found. | 961 * creates a new constructor body, if none can be found. |
| 962 * | 962 * |
| 963 * Returns [:null:] if the constructor does not have a body. | 963 * Returns [:null:] if the constructor does not have a body. |
| 964 */ | 964 */ |
| 965 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 965 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { |
| 966 assert(constructor.isGenerativeConstructor()); | 966 assert(constructor.isGenerativeConstructor()); |
| 967 assert(invariant(constructor, constructor.isImplementation)); | 967 assert(invariant(constructor, constructor.isImplementation)); |
| 968 if (constructor is SynthesizedConstructorElement) return null; | 968 if (constructor is SynthesizedConstructorElement) return null; |
| 969 FunctionExpression node = constructor.parseNode(compiler); | 969 FunctionExpression node = constructor.parseNode(compiler); |
| 970 // If we know the body doesn't have any code, we don't generate it. | 970 // If we know the body doesn't have any code, we don't generate it. |
| 971 if (node.body.asBlock() != null) { | 971 if (node.body.asBlock() != null) { |
| 972 NodeList statements = node.body.asBlock().statements; | 972 NodeList statements = node.body.asBlock().statements; |
| 973 if (statements.isEmpty()) return null; | 973 if (statements.isEmpty) return null; |
| 974 } | 974 } |
| 975 ClassElement classElement = constructor.getEnclosingClass(); | 975 ClassElement classElement = constructor.getEnclosingClass(); |
| 976 ConstructorBodyElement bodyElement; | 976 ConstructorBodyElement bodyElement; |
| 977 for (Link<Element> backendMembers = classElement.backendMembers; | 977 for (Link<Element> backendMembers = classElement.backendMembers; |
| 978 !backendMembers.isEmpty(); | 978 !backendMembers.isEmpty; |
| 979 backendMembers = backendMembers.tail) { | 979 backendMembers = backendMembers.tail) { |
| 980 Element backendMember = backendMembers.head; | 980 Element backendMember = backendMembers.head; |
| 981 if (backendMember.isGenerativeConstructorBody()) { | 981 if (backendMember.isGenerativeConstructorBody()) { |
| 982 ConstructorBodyElement body = backendMember; | 982 ConstructorBodyElement body = backendMember; |
| 983 if (body.constructor == constructor) { | 983 if (body.constructor == constructor) { |
| 984 bodyElement = backendMember; | 984 bodyElement = backendMember; |
| 985 break; | 985 break; |
| 986 } | 986 } |
| 987 } | 987 } |
| 988 } | 988 } |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 void buildInitializers(FunctionElement constructor, | 1180 void buildInitializers(FunctionElement constructor, |
| 1181 List<FunctionElement> constructors, | 1181 List<FunctionElement> constructors, |
| 1182 Map<Element, HInstruction> fieldValues) { | 1182 Map<Element, HInstruction> fieldValues) { |
| 1183 assert(invariant(constructor, constructor.isImplementation)); | 1183 assert(invariant(constructor, constructor.isImplementation)); |
| 1184 FunctionExpression functionNode = constructor.parseNode(compiler); | 1184 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 1185 | 1185 |
| 1186 bool foundSuperOrRedirect = false; | 1186 bool foundSuperOrRedirect = false; |
| 1187 | 1187 |
| 1188 if (functionNode.initializers != null) { | 1188 if (functionNode.initializers != null) { |
| 1189 Link<Node> initializers = functionNode.initializers.nodes; | 1189 Link<Node> initializers = functionNode.initializers.nodes; |
| 1190 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { | 1190 for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) { |
| 1191 assert(link.head is Send); | 1191 assert(link.head is Send); |
| 1192 if (link.head is !SendSet) { | 1192 if (link.head is !SendSet) { |
| 1193 // A super initializer or constructor redirection. | 1193 // A super initializer or constructor redirection. |
| 1194 Send call = link.head; | 1194 Send call = link.head; |
| 1195 assert(Initializers.isSuperConstructorCall(call) || | 1195 assert(Initializers.isSuperConstructorCall(call) || |
| 1196 Initializers.isConstructorRedirect(call)); | 1196 Initializers.isConstructorRedirect(call)); |
| 1197 FunctionElement target = elements[call]; | 1197 FunctionElement target = elements[call]; |
| 1198 Selector selector = elements.getSelector(call); | 1198 Selector selector = elements.getSelector(call); |
| 1199 Link<Node> arguments = call.arguments; | 1199 Link<Node> arguments = call.arguments; |
| 1200 inlineSuperOrRedirect(target, selector, arguments, constructors, | 1200 inlineSuperOrRedirect(target, selector, arguments, constructors, |
| 1201 fieldValues); | 1201 fieldValues); |
| 1202 foundSuperOrRedirect = true; | 1202 foundSuperOrRedirect = true; |
| 1203 } else { | 1203 } else { |
| 1204 // A field initializer. | 1204 // A field initializer. |
| 1205 SendSet init = link.head; | 1205 SendSet init = link.head; |
| 1206 Link<Node> arguments = init.arguments; | 1206 Link<Node> arguments = init.arguments; |
| 1207 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); | 1207 assert(!arguments.isEmpty && arguments.tail.isEmpty); |
| 1208 sourceElementStack.add(constructor); | 1208 sourceElementStack.add(constructor); |
| 1209 visit(arguments.head); | 1209 visit(arguments.head); |
| 1210 sourceElementStack.removeLast(); | 1210 sourceElementStack.removeLast(); |
| 1211 fieldValues[elements[init]] = pop(); | 1211 fieldValues[elements[init]] = pop(); |
| 1212 } | 1212 } |
| 1213 } | 1213 } |
| 1214 } | 1214 } |
| 1215 | 1215 |
| 1216 if (!foundSuperOrRedirect) { | 1216 if (!foundSuperOrRedirect) { |
| 1217 // No super initializer found. Try to find the default constructor if | 1217 // No super initializer found. Try to find the default constructor if |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1588 } | 1588 } |
| 1589 return location; | 1589 return location; |
| 1590 } | 1590 } |
| 1591 | 1591 |
| 1592 void visit(Node node) { | 1592 void visit(Node node) { |
| 1593 if (node != null) node.accept(this); | 1593 if (node != null) node.accept(this); |
| 1594 } | 1594 } |
| 1595 | 1595 |
| 1596 visitBlock(Block node) { | 1596 visitBlock(Block node) { |
| 1597 for (Link<Node> link = node.statements.nodes; | 1597 for (Link<Node> link = node.statements.nodes; |
| 1598 !link.isEmpty(); | 1598 !link.isEmpty; |
| 1599 link = link.tail) { | 1599 link = link.tail) { |
| 1600 visit(link.head); | 1600 visit(link.head); |
| 1601 if (isAborted()) { | 1601 if (isAborted()) { |
| 1602 // The block has been aborted by a return or a throw. | 1602 // The block has been aborted by a return or a throw. |
| 1603 if (!stack.isEmpty()) compiler.cancel('non-empty instruction stack'); | 1603 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack'); |
| 1604 return; | 1604 return; |
| 1605 } | 1605 } |
| 1606 } | 1606 } |
| 1607 assert(!current.isClosed()); | 1607 assert(!current.isClosed()); |
| 1608 if (!stack.isEmpty()) compiler.cancel('non-empty instruction stack'); | 1608 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack'); |
| 1609 } | 1609 } |
| 1610 | 1610 |
| 1611 visitClassNode(ClassNode node) { | 1611 visitClassNode(ClassNode node) { |
| 1612 compiler.internalError('visitClassNode should not be called', node: node); | 1612 compiler.internalError('visitClassNode should not be called', node: node); |
| 1613 } | 1613 } |
| 1614 | 1614 |
| 1615 visitExpressionStatement(ExpressionStatement node) { | 1615 visitExpressionStatement(ExpressionStatement node) { |
| 1616 visit(node.expression); | 1616 visit(node.expression); |
| 1617 pop(); | 1617 pop(); |
| 1618 } | 1618 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1650 HBasicBlock loopExitBlock = addNewBlock(); | 1650 HBasicBlock loopExitBlock = addNewBlock(); |
| 1651 assert(branchBlock.successors.length == 1); | 1651 assert(branchBlock.successors.length == 1); |
| 1652 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 1652 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
| 1653 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 1653 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
| 1654 breakInstruction.block.addSuccessor(loopExitBlock); | 1654 breakInstruction.block.addSuccessor(loopExitBlock); |
| 1655 breakLocals.add(locals); | 1655 breakLocals.add(locals); |
| 1656 }); | 1656 }); |
| 1657 branchBlock.addSuccessor(loopExitBlock); | 1657 branchBlock.addSuccessor(loopExitBlock); |
| 1658 open(loopExitBlock); | 1658 open(loopExitBlock); |
| 1659 localsHandler.endLoop(loopEntry); | 1659 localsHandler.endLoop(loopEntry); |
| 1660 if (!breakLocals.isEmpty()) { | 1660 if (!breakLocals.isEmpty) { |
| 1661 breakLocals.add(savedLocals); | 1661 breakLocals.add(savedLocals); |
| 1662 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock); | 1662 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock); |
| 1663 } else { | 1663 } else { |
| 1664 localsHandler = savedLocals; | 1664 localsHandler = savedLocals; |
| 1665 } | 1665 } |
| 1666 } | 1666 } |
| 1667 | 1667 |
| 1668 HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) { | 1668 HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) { |
| 1669 if (statements == null) return null; | 1669 if (statements == null) return null; |
| 1670 return new HSubGraphBlockInformation(statements); | 1670 return new HSubGraphBlockInformation(statements); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1744 bodyBlock.addSuccessor(updateBlock); | 1744 bodyBlock.addSuccessor(updateBlock); |
| 1745 continueLocals.add(localsHandler); | 1745 continueLocals.add(localsHandler); |
| 1746 | 1746 |
| 1747 open(updateBlock); | 1747 open(updateBlock); |
| 1748 | 1748 |
| 1749 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); | 1749 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); |
| 1750 | 1750 |
| 1751 HLabeledBlockInformation labelInfo; | 1751 HLabeledBlockInformation labelInfo; |
| 1752 List<LabelElement> labels = jumpHandler.labels(); | 1752 List<LabelElement> labels = jumpHandler.labels(); |
| 1753 TargetElement target = elements[loop]; | 1753 TargetElement target = elements[loop]; |
| 1754 if (!labels.isEmpty()) { | 1754 if (!labels.isEmpty) { |
| 1755 beginBodyBlock.setBlockFlow( | 1755 beginBodyBlock.setBlockFlow( |
| 1756 new HLabeledBlockInformation( | 1756 new HLabeledBlockInformation( |
| 1757 new HSubGraphBlockInformation(bodyGraph), | 1757 new HSubGraphBlockInformation(bodyGraph), |
| 1758 jumpHandler.labels(), | 1758 jumpHandler.labels(), |
| 1759 isContinue: true), | 1759 isContinue: true), |
| 1760 updateBlock); | 1760 updateBlock); |
| 1761 } else if (target != null && target.isContinueTarget) { | 1761 } else if (target != null && target.isContinueTarget) { |
| 1762 beginBodyBlock.setBlockFlow( | 1762 beginBodyBlock.setBlockFlow( |
| 1763 new HLabeledBlockInformation.implicit( | 1763 new HLabeledBlockInformation.implicit( |
| 1764 new HSubGraphBlockInformation(bodyGraph), | 1764 new HSubGraphBlockInformation(bodyGraph), |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1866 // block. This could also lead to a block having multiple entries and exits. | 1866 // block. This could also lead to a block having multiple entries and exits. |
| 1867 HBasicBlock bodyExitBlock = close(new HGoto()); | 1867 HBasicBlock bodyExitBlock = close(new HGoto()); |
| 1868 HBasicBlock conditionBlock = addNewBlock(); | 1868 HBasicBlock conditionBlock = addNewBlock(); |
| 1869 | 1869 |
| 1870 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1870 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
| 1871 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 1871 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { |
| 1872 instruction.block.addSuccessor(conditionBlock); | 1872 instruction.block.addSuccessor(conditionBlock); |
| 1873 continueLocals.add(locals); | 1873 continueLocals.add(locals); |
| 1874 }); | 1874 }); |
| 1875 bodyExitBlock.addSuccessor(conditionBlock); | 1875 bodyExitBlock.addSuccessor(conditionBlock); |
| 1876 if (!continueLocals.isEmpty()) { | 1876 if (!continueLocals.isEmpty) { |
| 1877 continueLocals.add(localsHandler); | 1877 continueLocals.add(localsHandler); |
| 1878 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); | 1878 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); |
| 1879 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 1879 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 1880 List<LabelElement> labels = jumpHandler.labels(); | 1880 List<LabelElement> labels = jumpHandler.labels(); |
| 1881 HSubGraphBlockInformation bodyInfo = | 1881 HSubGraphBlockInformation bodyInfo = |
| 1882 new HSubGraphBlockInformation(bodyGraph); | 1882 new HSubGraphBlockInformation(bodyGraph); |
| 1883 HLabeledBlockInformation info; | 1883 HLabeledBlockInformation info; |
| 1884 if (!labels.isEmpty()) { | 1884 if (!labels.isEmpty) { |
| 1885 info = new HLabeledBlockInformation(bodyInfo, labels, isContinue: true); | 1885 info = new HLabeledBlockInformation(bodyInfo, labels, isContinue: true); |
| 1886 } else { | 1886 } else { |
| 1887 info = new HLabeledBlockInformation.implicit(bodyInfo, target, | 1887 info = new HLabeledBlockInformation.implicit(bodyInfo, target, |
| 1888 isContinue: true); | 1888 isContinue: true); |
| 1889 } | 1889 } |
| 1890 bodyEntryBlock.setBlockFlow(info, conditionBlock); | 1890 bodyEntryBlock.setBlockFlow(info, conditionBlock); |
| 1891 } | 1891 } |
| 1892 open(conditionBlock); | 1892 open(conditionBlock); |
| 1893 | 1893 |
| 1894 visit(node.condition); | 1894 visit(node.condition); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1927 compiler.closureToClassMapper.getMappingForNestedFunction(node); | 1927 compiler.closureToClassMapper.getMappingForNestedFunction(node); |
| 1928 assert(nestedClosureData != null); | 1928 assert(nestedClosureData != null); |
| 1929 assert(nestedClosureData.closureClassElement != null); | 1929 assert(nestedClosureData.closureClassElement != null); |
| 1930 ClassElement closureClassElement = | 1930 ClassElement closureClassElement = |
| 1931 nestedClosureData.closureClassElement; | 1931 nestedClosureData.closureClassElement; |
| 1932 FunctionElement callElement = nestedClosureData.callElement; | 1932 FunctionElement callElement = nestedClosureData.callElement; |
| 1933 // TODO(ahe): This should be registered in codegen, not here. | 1933 // TODO(ahe): This should be registered in codegen, not here. |
| 1934 compiler.enqueuer.codegen.addToWorkList(callElement, elements); | 1934 compiler.enqueuer.codegen.addToWorkList(callElement, elements); |
| 1935 // TODO(ahe): This should be registered in codegen, not here. | 1935 // TODO(ahe): This should be registered in codegen, not here. |
| 1936 compiler.enqueuer.codegen.registerInstantiatedClass(closureClassElement); | 1936 compiler.enqueuer.codegen.registerInstantiatedClass(closureClassElement); |
| 1937 assert(closureClassElement.localScope.isEmpty()); | 1937 assert(closureClassElement.localScope.isEmpty); |
| 1938 | 1938 |
| 1939 List<HInstruction> capturedVariables = <HInstruction>[]; | 1939 List<HInstruction> capturedVariables = <HInstruction>[]; |
| 1940 for (Element member in closureClassElement.backendMembers) { | 1940 for (Element member in closureClassElement.backendMembers) { |
| 1941 // The backendMembers also contains the call method(s). We are only | 1941 // The backendMembers also contains the call method(s). We are only |
| 1942 // interested in the fields. | 1942 // interested in the fields. |
| 1943 if (member.isField()) { | 1943 if (member.isField()) { |
| 1944 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; | 1944 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; |
| 1945 assert(capturedLocal != null); | 1945 assert(capturedLocal != null); |
| 1946 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 1946 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
| 1947 } | 1947 } |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2388 arguments = arguments.tail, i++) { | 2388 arguments = arguments.tail, i++) { |
| 2389 visit(arguments.head); | 2389 visit(arguments.head); |
| 2390 list.add(pop()); | 2390 list.add(pop()); |
| 2391 } | 2391 } |
| 2392 | 2392 |
| 2393 // Visit named arguments and add them into a temporary map. | 2393 // Visit named arguments and add them into a temporary map. |
| 2394 Map<SourceString, HInstruction> instructions = | 2394 Map<SourceString, HInstruction> instructions = |
| 2395 new Map<SourceString, HInstruction>(); | 2395 new Map<SourceString, HInstruction>(); |
| 2396 List<SourceString> namedArguments = selector.namedArguments; | 2396 List<SourceString> namedArguments = selector.namedArguments; |
| 2397 int nameIndex = 0; | 2397 int nameIndex = 0; |
| 2398 for (; !arguments.isEmpty(); arguments = arguments.tail) { | 2398 for (; !arguments.isEmpty; arguments = arguments.tail) { |
| 2399 visit(arguments.head); | 2399 visit(arguments.head); |
| 2400 instructions[namedArguments[nameIndex++]] = pop(); | 2400 instructions[namedArguments[nameIndex++]] = pop(); |
| 2401 } | 2401 } |
| 2402 | 2402 |
| 2403 // Iterate through the named arguments to add them to the list | 2403 // Iterate through the named arguments to add them to the list |
| 2404 // of instructions, in an order that can be shared with | 2404 // of instructions, in an order that can be shared with |
| 2405 // selectors with the same named arguments. | 2405 // selectors with the same named arguments. |
| 2406 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); | 2406 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); |
| 2407 for (SourceString name in orderedNames) { | 2407 for (SourceString name in orderedNames) { |
| 2408 list.add(instructions[name]); | 2408 list.add(instructions[name]); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2440 | 2440 |
| 2441 return selector.addArgumentsToList(arguments, | 2441 return selector.addArgumentsToList(arguments, |
| 2442 list, | 2442 list, |
| 2443 element, | 2443 element, |
| 2444 compileArgument, | 2444 compileArgument, |
| 2445 compileConstant, | 2445 compileConstant, |
| 2446 compiler); | 2446 compiler); |
| 2447 } | 2447 } |
| 2448 | 2448 |
| 2449 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 2449 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 2450 for (; !link.isEmpty(); link = link.tail) { | 2450 for (; !link.isEmpty; link = link.tail) { |
| 2451 visit(link.head); | 2451 visit(link.head); |
| 2452 list.add(pop()); | 2452 list.add(pop()); |
| 2453 } | 2453 } |
| 2454 } | 2454 } |
| 2455 | 2455 |
| 2456 visitDynamicSend(Send node) { | 2456 visitDynamicSend(Send node) { |
| 2457 Selector selector = elements.getSelector(node); | 2457 Selector selector = elements.getSelector(node); |
| 2458 var inputs = <HInstruction>[]; | 2458 var inputs = <HInstruction>[]; |
| 2459 | 2459 |
| 2460 SourceString dartMethodName; | 2460 SourceString dartMethodName; |
| 2461 bool isNotEquals = false; | 2461 bool isNotEquals = false; |
| 2462 if (node.isIndex && !node.arguments.tail.isEmpty()) { | 2462 if (node.isIndex && !node.arguments.tail.isEmpty) { |
| 2463 dartMethodName = Elements.constructOperatorName( | 2463 dartMethodName = Elements.constructOperatorName( |
| 2464 const SourceString('[]='), false); | 2464 const SourceString('[]='), false); |
| 2465 } else if (node.selector.asOperator() != null) { | 2465 } else if (node.selector.asOperator() != null) { |
| 2466 SourceString name = node.selector.asIdentifier().source; | 2466 SourceString name = node.selector.asIdentifier().source; |
| 2467 isNotEquals = identical(name.stringValue, '!='); | 2467 isNotEquals = identical(name.stringValue, '!='); |
| 2468 dartMethodName = Elements.constructOperatorName( | 2468 dartMethodName = Elements.constructOperatorName( |
| 2469 name, node.argumentsNode is Prefix); | 2469 name, node.argumentsNode is Prefix); |
| 2470 } else { | 2470 } else { |
| 2471 dartMethodName = node.selector.asIdentifier().source; | 2471 dartMethodName = node.selector.asIdentifier().source; |
| 2472 } | 2472 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2521 inputs.add(closureTarget); | 2521 inputs.add(closureTarget); |
| 2522 addDynamicSendArgumentsToList(node, inputs); | 2522 addDynamicSendArgumentsToList(node, inputs); |
| 2523 pushWithPosition(new HInvokeClosure(selector, inputs), node); | 2523 pushWithPosition(new HInvokeClosure(selector, inputs), node); |
| 2524 } | 2524 } |
| 2525 | 2525 |
| 2526 void handleForeignJs(Send node) { | 2526 void handleForeignJs(Send node) { |
| 2527 Link<Node> link = node.arguments; | 2527 Link<Node> link = node.arguments; |
| 2528 // If the invoke is on foreign code, don't visit the first | 2528 // If the invoke is on foreign code, don't visit the first |
| 2529 // argument, which is the type, and the second argument, | 2529 // argument, which is the type, and the second argument, |
| 2530 // which is the foreign code. | 2530 // which is the foreign code. |
| 2531 if (link.isEmpty() || link.tail.isEmpty()) { | 2531 if (link.isEmpty || link.tail.isEmpty) { |
| 2532 compiler.cancel('At least two arguments expected', | 2532 compiler.cancel('At least two arguments expected', |
| 2533 node: node.argumentsNode); | 2533 node: node.argumentsNode); |
| 2534 } | 2534 } |
| 2535 List<HInstruction> inputs = <HInstruction>[]; | 2535 List<HInstruction> inputs = <HInstruction>[]; |
| 2536 Node type = link.head; | 2536 Node type = link.head; |
| 2537 Node code = link.tail.head; | 2537 Node code = link.tail.head; |
| 2538 addGenericSendArgumentsToList(link.tail.tail, inputs); | 2538 addGenericSendArgumentsToList(link.tail.tail, inputs); |
| 2539 | 2539 |
| 2540 if (type is !LiteralString) { | 2540 if (type is !LiteralString) { |
| 2541 // The type must not be a juxtaposition or interpolation. | 2541 // The type must not be a juxtaposition or interpolation. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2552 typeString.dartString, | 2552 typeString.dartString, |
| 2553 inputs)); | 2553 inputs)); |
| 2554 return; | 2554 return; |
| 2555 } | 2555 } |
| 2556 } | 2556 } |
| 2557 compiler.cancel('JS code must be a string literal', node: code); | 2557 compiler.cancel('JS code must be a string literal', node: code); |
| 2558 } | 2558 } |
| 2559 | 2559 |
| 2560 void handleForeignUnintercepted(Send node) { | 2560 void handleForeignUnintercepted(Send node) { |
| 2561 Link<Node> link = node.arguments; | 2561 Link<Node> link = node.arguments; |
| 2562 if (!link.tail.isEmpty()) { | 2562 if (!link.tail.isEmpty) { |
| 2563 compiler.cancel( | 2563 compiler.cancel( |
| 2564 'More than one expression in UNINTERCEPTED()', node: node); | 2564 'More than one expression in UNINTERCEPTED()', node: node); |
| 2565 } | 2565 } |
| 2566 Expression expression = link.head; | 2566 Expression expression = link.head; |
| 2567 disableMethodInterception(); | 2567 disableMethodInterception(); |
| 2568 visit(expression); | 2568 visit(expression); |
| 2569 enableMethodInterception(); | 2569 enableMethodInterception(); |
| 2570 } | 2570 } |
| 2571 | 2571 |
| 2572 void handleForeignJsHasEquals(Send node) { | 2572 void handleForeignJsHasEquals(Send node) { |
| 2573 List<HInstruction> inputs = <HInstruction>[]; | 2573 List<HInstruction> inputs = <HInstruction>[]; |
| 2574 if (!node.arguments.tail.isEmpty()) { | 2574 if (!node.arguments.tail.isEmpty) { |
| 2575 compiler.cancel( | 2575 compiler.cancel( |
| 2576 'More than one expression in JS_HAS_EQUALS()', node: node); | 2576 'More than one expression in JS_HAS_EQUALS()', node: node); |
| 2577 } | 2577 } |
| 2578 addGenericSendArgumentsToList(node.arguments, inputs); | 2578 addGenericSendArgumentsToList(node.arguments, inputs); |
| 2579 String name = backend.namer.publicInstanceMethodNameByArity( | 2579 String name = backend.namer.publicInstanceMethodNameByArity( |
| 2580 Elements.OPERATOR_EQUALS, 1); | 2580 Elements.OPERATOR_EQUALS, 1); |
| 2581 push(new HForeign(new DartString.literal('!!#.$name'), | 2581 push(new HForeign(new DartString.literal('!!#.$name'), |
| 2582 const LiteralDartString('bool'), | 2582 const LiteralDartString('bool'), |
| 2583 inputs)); | 2583 inputs)); |
| 2584 } | 2584 } |
| 2585 | 2585 |
| 2586 void handleForeignJsCurrentIsolate(Send node) { | 2586 void handleForeignJsCurrentIsolate(Send node) { |
| 2587 if (!node.arguments.isEmpty()) { | 2587 if (!node.arguments.isEmpty) { |
| 2588 compiler.cancel( | 2588 compiler.cancel( |
| 2589 'Too many arguments to JS_CURRENT_ISOLATE', node: node); | 2589 'Too many arguments to JS_CURRENT_ISOLATE', node: node); |
| 2590 } | 2590 } |
| 2591 | 2591 |
| 2592 if (!compiler.hasIsolateSupport()) { | 2592 if (!compiler.hasIsolateSupport()) { |
| 2593 // If the isolate library is not used, we just generate code | 2593 // If the isolate library is not used, we just generate code |
| 2594 // to fetch the Leg's current isolate. | 2594 // to fetch the Leg's current isolate. |
| 2595 String name = backend.namer.CURRENT_ISOLATE; | 2595 String name = backend.namer.CURRENT_ISOLATE; |
| 2596 push(new HForeign(new DartString.literal(name), | 2596 push(new HForeign(new DartString.literal(name), |
| 2597 const LiteralDartString('var'), | 2597 const LiteralDartString('var'), |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2628 } | 2628 } |
| 2629 HStatic target = new HStatic(element); | 2629 HStatic target = new HStatic(element); |
| 2630 add(target); | 2630 add(target); |
| 2631 List<HInstruction> inputs = <HInstruction>[target]; | 2631 List<HInstruction> inputs = <HInstruction>[target]; |
| 2632 addGenericSendArgumentsToList(link, inputs); | 2632 addGenericSendArgumentsToList(link, inputs); |
| 2633 push(new HInvokeStatic(inputs)); | 2633 push(new HInvokeStatic(inputs)); |
| 2634 } | 2634 } |
| 2635 } | 2635 } |
| 2636 | 2636 |
| 2637 void handleForeignDartClosureToJs(Send node) { | 2637 void handleForeignDartClosureToJs(Send node) { |
| 2638 if (node.arguments.isEmpty() || !node.arguments.tail.isEmpty()) { | 2638 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
| 2639 compiler.cancel('Exactly one argument required', | 2639 compiler.cancel('Exactly one argument required', |
| 2640 node: node.argumentsNode); | 2640 node: node.argumentsNode); |
| 2641 } | 2641 } |
| 2642 Node closure = node.arguments.head; | 2642 Node closure = node.arguments.head; |
| 2643 Element element = elements[closure]; | 2643 Element element = elements[closure]; |
| 2644 if (!Elements.isStaticOrTopLevelFunction(element)) { | 2644 if (!Elements.isStaticOrTopLevelFunction(element)) { |
| 2645 compiler.cancel( | 2645 compiler.cancel( |
| 2646 'JS_TO_CLOSURE requires a static or top-level method', | 2646 'JS_TO_CLOSURE requires a static or top-level method', |
| 2647 node: closure); | 2647 node: closure); |
| 2648 } | 2648 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2799 * Var # [getRuntimeType(this).Var] | 2799 * Var # [getRuntimeType(this).Var] |
| 2800 * C<int, D<Var>> 'C<int, D<' + # + '>>' [getRuntimeType(this).Var] | 2800 * C<int, D<Var>> 'C<int, D<' + # + '>>' [getRuntimeType(this).Var] |
| 2801 */ | 2801 */ |
| 2802 void buildTypeString(DartType type, {isInQuotes: false}) { | 2802 void buildTypeString(DartType type, {isInQuotes: false}) { |
| 2803 if (type is TypeVariableType) { | 2803 if (type is TypeVariableType) { |
| 2804 addTypeVariableReference(type); | 2804 addTypeVariableReference(type); |
| 2805 template.add(isInQuotes ? "' + # +'" : "#"); | 2805 template.add(isInQuotes ? "' + # +'" : "#"); |
| 2806 } else if (type is InterfaceType) { | 2806 } else if (type is InterfaceType) { |
| 2807 bool isFirstVariable = true; | 2807 bool isFirstVariable = true; |
| 2808 InterfaceType interfaceType = type; | 2808 InterfaceType interfaceType = type; |
| 2809 bool hasTypeArguments = !interfaceType.arguments.isEmpty(); | 2809 bool hasTypeArguments = !interfaceType.arguments.isEmpty; |
| 2810 if (!isInQuotes) template.add("'"); | 2810 if (!isInQuotes) template.add("'"); |
| 2811 template.add(rti.getName(type.element)); | 2811 template.add(rti.getName(type.element)); |
| 2812 if (hasTypeArguments) { | 2812 if (hasTypeArguments) { |
| 2813 template.add("<"); | 2813 template.add("<"); |
| 2814 for (DartType argument in interfaceType.arguments) { | 2814 for (DartType argument in interfaceType.arguments) { |
| 2815 if (!isFirstVariable) { | 2815 if (!isFirstVariable) { |
| 2816 template.add(", "); | 2816 template.add(", "); |
| 2817 } else { | 2817 } else { |
| 2818 isFirstVariable = false; | 2818 isFirstVariable = false; |
| 2819 } | 2819 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2846 List<HInstruction> inputs = <HInstruction>[]; | 2846 List<HInstruction> inputs = <HInstruction>[]; |
| 2847 type.arguments.forEach((DartType argument) { | 2847 type.arguments.forEach((DartType argument) { |
| 2848 inputs.add(analyzeTypeArgument(argument, currentNode)); | 2848 inputs.add(analyzeTypeArgument(argument, currentNode)); |
| 2849 }); | 2849 }); |
| 2850 callSetRuntimeTypeInfo(type.element, inputs, newObject); | 2850 callSetRuntimeTypeInfo(type.element, inputs, newObject); |
| 2851 } | 2851 } |
| 2852 | 2852 |
| 2853 void callSetRuntimeTypeInfo(ClassElement element, | 2853 void callSetRuntimeTypeInfo(ClassElement element, |
| 2854 List<HInstruction> rtiInputs, | 2854 List<HInstruction> rtiInputs, |
| 2855 HInstruction newObject) { | 2855 HInstruction newObject) { |
| 2856 bool needsRti = compiler.world.needsRti(element) && !rtiInputs.isEmpty(); | 2856 bool needsRti = compiler.world.needsRti(element) && !rtiInputs.isEmpty; |
| 2857 bool runtimeTypeIsUsed = compiler.enabledRuntimeType; | 2857 bool runtimeTypeIsUsed = compiler.enabledRuntimeType; |
| 2858 if (!needsRti && !runtimeTypeIsUsed) return; | 2858 if (!needsRti && !runtimeTypeIsUsed) return; |
| 2859 | 2859 |
| 2860 HInstruction createForeign(String template, | 2860 HInstruction createForeign(String template, |
| 2861 List<HInstruction> arguments, | 2861 List<HInstruction> arguments, |
| 2862 [String type = 'String']) { | 2862 [String type = 'String']) { |
| 2863 return new HForeign(new LiteralDartString(template), | 2863 return new HForeign(new LiteralDartString(template), |
| 2864 new LiteralDartString(type), | 2864 new LiteralDartString(type), |
| 2865 arguments); | 2865 arguments); |
| 2866 } | 2866 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2897 add(new HInvokeStatic( | 2897 add(new HInvokeStatic( |
| 2898 <HInstruction>[typeInfoSetter, newObject, runtimeInfo])); | 2898 <HInstruction>[typeInfoSetter, newObject, runtimeInfo])); |
| 2899 } | 2899 } |
| 2900 | 2900 |
| 2901 visitNewSend(Send node) { | 2901 visitNewSend(Send node) { |
| 2902 bool isListConstructor = false; | 2902 bool isListConstructor = false; |
| 2903 computeType(element) { | 2903 computeType(element) { |
| 2904 Element originalElement = elements[node]; | 2904 Element originalElement = elements[node]; |
| 2905 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) { | 2905 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) { |
| 2906 isListConstructor = true; | 2906 isListConstructor = true; |
| 2907 if (node.arguments.isEmpty()) { | 2907 if (node.arguments.isEmpty) { |
| 2908 return HType.EXTENDABLE_ARRAY; | 2908 return HType.EXTENDABLE_ARRAY; |
| 2909 } else { | 2909 } else { |
| 2910 return HType.MUTABLE_ARRAY; | 2910 return HType.MUTABLE_ARRAY; |
| 2911 } | 2911 } |
| 2912 } else if (element.isGenerativeConstructor()) { | 2912 } else if (element.isGenerativeConstructor()) { |
| 2913 ClassElement cls = element.getEnclosingClass(); | 2913 ClassElement cls = element.getEnclosingClass(); |
| 2914 return new HBoundedType.exact(cls.type); | 2914 return new HBoundedType.exact(cls.type); |
| 2915 } else { | 2915 } else { |
| 2916 return HType.UNKNOWN; | 2916 return HType.UNKNOWN; |
| 2917 } | 2917 } |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3162 if (isPrefix) { | 3162 if (isPrefix) { |
| 3163 stack.add(value); | 3163 stack.add(value); |
| 3164 } else { | 3164 } else { |
| 3165 stack.add(left); | 3165 stack.add(left); |
| 3166 } | 3166 } |
| 3167 } | 3167 } |
| 3168 } | 3168 } |
| 3169 } else if (const SourceString("=") == op.source) { | 3169 } else if (const SourceString("=") == op.source) { |
| 3170 Element element = elements[node]; | 3170 Element element = elements[node]; |
| 3171 Link<Node> link = node.arguments; | 3171 Link<Node> link = node.arguments; |
| 3172 assert(!link.isEmpty() && link.tail.isEmpty()); | 3172 assert(!link.isEmpty && link.tail.isEmpty); |
| 3173 visit(link.head); | 3173 visit(link.head); |
| 3174 HInstruction value = pop(); | 3174 HInstruction value = pop(); |
| 3175 generateSetter(node, element, value); | 3175 generateSetter(node, element, value); |
| 3176 } else if (identical(op.source.stringValue, "is")) { | 3176 } else if (identical(op.source.stringValue, "is")) { |
| 3177 compiler.internalError("is-operator as SendSet", node: op); | 3177 compiler.internalError("is-operator as SendSet", node: op); |
| 3178 } else { | 3178 } else { |
| 3179 assert(const SourceString("++") == op.source || | 3179 assert(const SourceString("++") == op.source || |
| 3180 const SourceString("--") == op.source || | 3180 const SourceString("--") == op.source || |
| 3181 node.assignmentOperator.source.stringValue.endsWith("=")); | 3181 node.assignmentOperator.source.stringValue.endsWith("=")); |
| 3182 Element element = elements[node]; | 3182 Element element = elements[node]; |
| 3183 bool isCompoundAssignment = !node.arguments.isEmpty(); | 3183 bool isCompoundAssignment = !node.arguments.isEmpty; |
| 3184 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. | 3184 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. |
| 3185 | 3185 |
| 3186 // [receiver] is only used if the node is an instance send. | 3186 // [receiver] is only used if the node is an instance send. |
| 3187 HInstruction receiver = null; | 3187 HInstruction receiver = null; |
| 3188 if (Elements.isInstanceSend(node, elements)) { | 3188 if (Elements.isInstanceSend(node, elements)) { |
| 3189 receiver = generateInstanceSendReceiver(node); | 3189 receiver = generateInstanceSendReceiver(node); |
| 3190 generateInstanceGetterWithCompiledReceiver(node, receiver); | 3190 generateInstanceGetterWithCompiledReceiver(node, receiver); |
| 3191 } else { | 3191 } else { |
| 3192 generateGetter(node, elements[node.selector]); | 3192 generateGetter(node, elements[node.selector]); |
| 3193 } | 3193 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3241 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); | 3241 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); |
| 3242 stringBuilder.visit(node); | 3242 stringBuilder.visit(node); |
| 3243 stack.add(stringBuilder.result); | 3243 stack.add(stringBuilder.result); |
| 3244 } | 3244 } |
| 3245 | 3245 |
| 3246 void visitLiteralNull(LiteralNull node) { | 3246 void visitLiteralNull(LiteralNull node) { |
| 3247 stack.add(graph.addConstantNull(constantSystem)); | 3247 stack.add(graph.addConstantNull(constantSystem)); |
| 3248 } | 3248 } |
| 3249 | 3249 |
| 3250 visitNodeList(NodeList node) { | 3250 visitNodeList(NodeList node) { |
| 3251 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 3251 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 3252 if (isAborted()) { | 3252 if (isAborted()) { |
| 3253 compiler.reportWarning(link.head, 'dead code'); | 3253 compiler.reportWarning(link.head, 'dead code'); |
| 3254 } else { | 3254 } else { |
| 3255 visit(link.head); | 3255 visit(link.head); |
| 3256 } | 3256 } |
| 3257 } | 3257 } |
| 3258 } | 3258 } |
| 3259 | 3259 |
| 3260 void visitParenthesizedExpression(ParenthesizedExpression node) { | 3260 void visitParenthesizedExpression(ParenthesizedExpression node) { |
| 3261 visit(node.expression); | 3261 visit(node.expression); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3286 compiler.internalError("Unimplemented: Redirecting factory constructor", | 3286 compiler.internalError("Unimplemented: Redirecting factory constructor", |
| 3287 node: node); | 3287 node: node); |
| 3288 } | 3288 } |
| 3289 HInstruction value; | 3289 HInstruction value; |
| 3290 if (node.expression == null) { | 3290 if (node.expression == null) { |
| 3291 value = graph.addConstantNull(constantSystem); | 3291 value = graph.addConstantNull(constantSystem); |
| 3292 } else { | 3292 } else { |
| 3293 visit(node.expression); | 3293 visit(node.expression); |
| 3294 value = pop(); | 3294 value = pop(); |
| 3295 } | 3295 } |
| 3296 if (!inliningStack.isEmpty()) { | 3296 if (!inliningStack.isEmpty) { |
| 3297 localsHandler.updateLocal(returnElement, value); | 3297 localsHandler.updateLocal(returnElement, value); |
| 3298 } else { | 3298 } else { |
| 3299 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); | 3299 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); |
| 3300 } | 3300 } |
| 3301 } | 3301 } |
| 3302 | 3302 |
| 3303 visitThrow(Throw node) { | 3303 visitThrow(Throw node) { |
| 3304 if (node.expression == null) { | 3304 if (node.expression == null) { |
| 3305 HInstruction exception = rethrowableException; | 3305 HInstruction exception = rethrowableException; |
| 3306 if (exception == null) { | 3306 if (exception == null) { |
| 3307 exception = graph.addConstantNull(constantSystem); | 3307 exception = graph.addConstantNull(constantSystem); |
| 3308 compiler.internalError( | 3308 compiler.internalError( |
| 3309 'rethrowableException should not be null', node: node); | 3309 'rethrowableException should not be null', node: node); |
| 3310 } | 3310 } |
| 3311 close(new HThrow(exception, isRethrow: true)); | 3311 close(new HThrow(exception, isRethrow: true)); |
| 3312 } else { | 3312 } else { |
| 3313 visit(node.expression); | 3313 visit(node.expression); |
| 3314 close(new HThrow(pop())); | 3314 close(new HThrow(pop())); |
| 3315 } | 3315 } |
| 3316 } | 3316 } |
| 3317 | 3317 |
| 3318 visitTypeAnnotation(TypeAnnotation node) { | 3318 visitTypeAnnotation(TypeAnnotation node) { |
| 3319 compiler.internalError('visiting type annotation in SSA builder', | 3319 compiler.internalError('visiting type annotation in SSA builder', |
| 3320 node: node); | 3320 node: node); |
| 3321 } | 3321 } |
| 3322 | 3322 |
| 3323 visitVariableDefinitions(VariableDefinitions node) { | 3323 visitVariableDefinitions(VariableDefinitions node) { |
| 3324 for (Link<Node> link = node.definitions.nodes; | 3324 for (Link<Node> link = node.definitions.nodes; |
| 3325 !link.isEmpty(); | 3325 !link.isEmpty; |
| 3326 link = link.tail) { | 3326 link = link.tail) { |
| 3327 Node definition = link.head; | 3327 Node definition = link.head; |
| 3328 if (definition is Identifier) { | 3328 if (definition is Identifier) { |
| 3329 HInstruction initialValue = graph.addConstantNull(constantSystem); | 3329 HInstruction initialValue = graph.addConstantNull(constantSystem); |
| 3330 localsHandler.updateLocal(elements[definition], initialValue); | 3330 localsHandler.updateLocal(elements[definition], initialValue); |
| 3331 } else { | 3331 } else { |
| 3332 assert(definition is SendSet); | 3332 assert(definition is SendSet); |
| 3333 visitSendSet(definition); | 3333 visitSendSet(definition); |
| 3334 pop(); // Discard value. | 3334 pop(); // Discard value. |
| 3335 } | 3335 } |
| 3336 } | 3336 } |
| 3337 } | 3337 } |
| 3338 | 3338 |
| 3339 visitLiteralList(LiteralList node) { | 3339 visitLiteralList(LiteralList node) { |
| 3340 if (node.isConst()) { | 3340 if (node.isConst()) { |
| 3341 ConstantHandler handler = compiler.constantHandler; | 3341 ConstantHandler handler = compiler.constantHandler; |
| 3342 Constant constant = handler.compileNodeWithDefinitions(node, elements); | 3342 Constant constant = handler.compileNodeWithDefinitions(node, elements); |
| 3343 stack.add(graph.addConstant(constant)); | 3343 stack.add(graph.addConstant(constant)); |
| 3344 return; | 3344 return; |
| 3345 } | 3345 } |
| 3346 | 3346 |
| 3347 List<HInstruction> inputs = <HInstruction>[]; | 3347 List<HInstruction> inputs = <HInstruction>[]; |
| 3348 for (Link<Node> link = node.elements.nodes; | 3348 for (Link<Node> link = node.elements.nodes; |
| 3349 !link.isEmpty(); | 3349 !link.isEmpty; |
| 3350 link = link.tail) { | 3350 link = link.tail) { |
| 3351 visit(link.head); | 3351 visit(link.head); |
| 3352 inputs.add(pop()); | 3352 inputs.add(pop()); |
| 3353 } | 3353 } |
| 3354 push(new HLiteralList(inputs)); | 3354 push(new HLiteralList(inputs)); |
| 3355 } | 3355 } |
| 3356 | 3356 |
| 3357 visitConditional(Conditional node) { | 3357 visitConditional(Conditional node) { |
| 3358 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 3358 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 3359 brancher.handleConditional(() => visit(node.condition), | 3359 brancher.handleConditional(() => visit(node.condition), |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3535 | 3535 |
| 3536 visitLiteralMap(LiteralMap node) { | 3536 visitLiteralMap(LiteralMap node) { |
| 3537 if (node.isConst()) { | 3537 if (node.isConst()) { |
| 3538 ConstantHandler handler = compiler.constantHandler; | 3538 ConstantHandler handler = compiler.constantHandler; |
| 3539 Constant constant = handler.compileNodeWithDefinitions(node, elements); | 3539 Constant constant = handler.compileNodeWithDefinitions(node, elements); |
| 3540 stack.add(graph.addConstant(constant)); | 3540 stack.add(graph.addConstant(constant)); |
| 3541 return; | 3541 return; |
| 3542 } | 3542 } |
| 3543 List<HInstruction> inputs = <HInstruction>[]; | 3543 List<HInstruction> inputs = <HInstruction>[]; |
| 3544 for (Link<Node> link = node.entries.nodes; | 3544 for (Link<Node> link = node.entries.nodes; |
| 3545 !link.isEmpty(); | 3545 !link.isEmpty; |
| 3546 link = link.tail) { | 3546 link = link.tail) { |
| 3547 visit(link.head); | 3547 visit(link.head); |
| 3548 inputs.addLast(pop()); | 3548 inputs.addLast(pop()); |
| 3549 inputs.addLast(pop()); | 3549 inputs.addLast(pop()); |
| 3550 } | 3550 } |
| 3551 HLiteralList keyValuePairs = new HLiteralList(inputs); | 3551 HLiteralList keyValuePairs = new HLiteralList(inputs); |
| 3552 add(keyValuePairs); | 3552 add(keyValuePairs); |
| 3553 pushInvokeHelper1(interceptors.getMapMaker(), keyValuePairs); | 3553 pushInvokeHelper1(interceptors.getMapMaker(), keyValuePairs); |
| 3554 } | 3554 } |
| 3555 | 3555 |
| 3556 visitLiteralMapEntry(LiteralMapEntry node) { | 3556 visitLiteralMapEntry(LiteralMapEntry node) { |
| 3557 visit(node.value); | 3557 visit(node.value); |
| 3558 visit(node.key); | 3558 visit(node.key); |
| 3559 } | 3559 } |
| 3560 | 3560 |
| 3561 visitNamedArgument(NamedArgument node) { | 3561 visitNamedArgument(NamedArgument node) { |
| 3562 visit(node.expression); | 3562 visit(node.expression); |
| 3563 } | 3563 } |
| 3564 | 3564 |
| 3565 visitSwitchStatement(SwitchStatement node) { | 3565 visitSwitchStatement(SwitchStatement node) { |
| 3566 if (tryBuildConstantSwitch(node)) return; | 3566 if (tryBuildConstantSwitch(node)) return; |
| 3567 | 3567 |
| 3568 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 3568 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 3569 HBasicBlock startBlock = openNewBlock(); | 3569 HBasicBlock startBlock = openNewBlock(); |
| 3570 visit(node.expression); | 3570 visit(node.expression); |
| 3571 HInstruction expression = pop(); | 3571 HInstruction expression = pop(); |
| 3572 if (node.cases.isEmpty()) { | 3572 if (node.cases.isEmpty) { |
| 3573 return; | 3573 return; |
| 3574 } | 3574 } |
| 3575 | 3575 |
| 3576 Link<Node> cases = node.cases.nodes; | 3576 Link<Node> cases = node.cases.nodes; |
| 3577 JumpHandler jumpHandler = createJumpHandler(node); | 3577 JumpHandler jumpHandler = createJumpHandler(node); |
| 3578 | 3578 |
| 3579 buildSwitchCases(cases, expression); | 3579 buildSwitchCases(cases, expression); |
| 3580 | 3580 |
| 3581 HBasicBlock lastBlock = lastOpenedBlock; | 3581 HBasicBlock lastBlock = lastOpenedBlock; |
| 3582 | 3582 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3661 if (failure) { | 3661 if (failure) { |
| 3662 return false; | 3662 return false; |
| 3663 } | 3663 } |
| 3664 | 3664 |
| 3665 // TODO(ngeoffray): Handle switch-instruction in bailout code. | 3665 // TODO(ngeoffray): Handle switch-instruction in bailout code. |
| 3666 work.allowSpeculativeOptimization = false; | 3666 work.allowSpeculativeOptimization = false; |
| 3667 // Then build a switch structure. | 3667 // Then build a switch structure. |
| 3668 HBasicBlock expressionStart = openNewBlock(); | 3668 HBasicBlock expressionStart = openNewBlock(); |
| 3669 visit(node.expression); | 3669 visit(node.expression); |
| 3670 HInstruction expression = pop(); | 3670 HInstruction expression = pop(); |
| 3671 if (node.cases.isEmpty()) { | 3671 if (node.cases.isEmpty) { |
| 3672 return true; | 3672 return true; |
| 3673 } | 3673 } |
| 3674 HBasicBlock expressionEnd = current; | 3674 HBasicBlock expressionEnd = current; |
| 3675 | 3675 |
| 3676 HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]); | 3676 HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]); |
| 3677 HBasicBlock expressionBlock = close(switchInstruction); | 3677 HBasicBlock expressionBlock = close(switchInstruction); |
| 3678 JumpHandler jumpHandler = createJumpHandler(node); | 3678 JumpHandler jumpHandler = createJumpHandler(node); |
| 3679 LocalsHandler savedLocals = localsHandler; | 3679 LocalsHandler savedLocals = localsHandler; |
| 3680 | 3680 |
| 3681 List<List<Constant>> matchExpressions = <List<Constant>>[]; | 3681 List<List<Constant>> matchExpressions = <List<Constant>>[]; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3827 compiler.reportWarning(node, 'Missing break at end of switch case'); | 3827 compiler.reportWarning(node, 'Missing break at end of switch case'); |
| 3828 Element element = | 3828 Element element = |
| 3829 compiler.findHelper(const SourceString("getFallThroughError")); | 3829 compiler.findHelper(const SourceString("getFallThroughError")); |
| 3830 pushInvokeHelper0(element); | 3830 pushInvokeHelper0(element); |
| 3831 HInstruction error = pop(); | 3831 HInstruction error = pop(); |
| 3832 close(new HThrow(error)); | 3832 close(new HThrow(error)); |
| 3833 } | 3833 } |
| 3834 } | 3834 } |
| 3835 | 3835 |
| 3836 Link<Node> skipLabels(Link<Node> labelsAndCases) { | 3836 Link<Node> skipLabels(Link<Node> labelsAndCases) { |
| 3837 while (!labelsAndCases.isEmpty() && labelsAndCases.head is Label) { | 3837 while (!labelsAndCases.isEmpty && labelsAndCases.head is Label) { |
| 3838 labelsAndCases = labelsAndCases.tail; | 3838 labelsAndCases = labelsAndCases.tail; |
| 3839 } | 3839 } |
| 3840 return labelsAndCases; | 3840 return labelsAndCases; |
| 3841 } | 3841 } |
| 3842 | 3842 |
| 3843 Link<Node> labelsAndCases = skipLabels(node.labelsAndCases.nodes); | 3843 Link<Node> labelsAndCases = skipLabels(node.labelsAndCases.nodes); |
| 3844 if (labelsAndCases.isEmpty()) { | 3844 if (labelsAndCases.isEmpty) { |
| 3845 // Default case with no expressions. | 3845 // Default case with no expressions. |
| 3846 if (!node.isDefaultCase) { | 3846 if (!node.isDefaultCase) { |
| 3847 compiler.internalError("Case with no expression and not default", | 3847 compiler.internalError("Case with no expression and not default", |
| 3848 node: node); | 3848 node: node); |
| 3849 } | 3849 } |
| 3850 visit(node.statements); | 3850 visit(node.statements); |
| 3851 // This must be the final case (otherwise "default" would be invalid), | 3851 // This must be the final case (otherwise "default" would be invalid), |
| 3852 // so we don't need to check for fallthrough. | 3852 // so we don't need to check for fallthrough. |
| 3853 return; | 3853 return; |
| 3854 } | 3854 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3870 if (constant != null) { | 3870 if (constant != null) { |
| 3871 stack.add(graph.addConstant(constant)); | 3871 stack.add(graph.addConstant(constant)); |
| 3872 } else { | 3872 } else { |
| 3873 visit(match.expression); | 3873 visit(match.expression); |
| 3874 } | 3874 } |
| 3875 push(new HEquals(target, pop(), expression)); | 3875 push(new HEquals(target, pop(), expression)); |
| 3876 } | 3876 } |
| 3877 | 3877 |
| 3878 // If this is the last expression, just return it. | 3878 // If this is the last expression, just return it. |
| 3879 Link<Node> tail = skipLabels(remainingCases.tail); | 3879 Link<Node> tail = skipLabels(remainingCases.tail); |
| 3880 if (tail.isEmpty()) { | 3880 if (tail.isEmpty) { |
| 3881 left(); | 3881 left(); |
| 3882 return; | 3882 return; |
| 3883 } | 3883 } |
| 3884 | 3884 |
| 3885 void right() { | 3885 void right() { |
| 3886 buildTests(tail); | 3886 buildTests(tail); |
| 3887 } | 3887 } |
| 3888 SsaBranchBuilder branchBuilder = | 3888 SsaBranchBuilder branchBuilder = |
| 3889 new SsaBranchBuilder(this, remainingCases.head); | 3889 new SsaBranchBuilder(this, remainingCases.head); |
| 3890 branchBuilder.handleLogicalAndOr(left, right, isAnd: false); | 3890 branchBuilder.handleLogicalAndOr(left, right, isAnd: false); |
| 3891 } | 3891 } |
| 3892 | 3892 |
| 3893 if (node.isDefaultCase) { | 3893 if (node.isDefaultCase) { |
| 3894 // Default case must be last. | 3894 // Default case must be last. |
| 3895 assert(cases.tail.isEmpty()); | 3895 assert(cases.tail.isEmpty); |
| 3896 // Perform the tests until one of them match, but then always execute the | 3896 // Perform the tests until one of them match, but then always execute the |
| 3897 // statements. | 3897 // statements. |
| 3898 // TODO(lrn): Stop performing tests when all expressions are compile-time | 3898 // TODO(lrn): Stop performing tests when all expressions are compile-time |
| 3899 // constant strings or integers. | 3899 // constant strings or integers. |
| 3900 handleIf(node, () { buildTests(labelsAndCases); }, (){}, null); | 3900 handleIf(node, () { buildTests(labelsAndCases); }, (){}, null); |
| 3901 visit(node.statements); | 3901 visit(node.statements); |
| 3902 } else { | 3902 } else { |
| 3903 if (cases.tail.isEmpty()) { | 3903 if (cases.tail.isEmpty) { |
| 3904 handleIf(node, | 3904 handleIf(node, |
| 3905 () { buildTests(labelsAndCases); }, | 3905 () { buildTests(labelsAndCases); }, |
| 3906 () { visit(node.statements); }, | 3906 () { visit(node.statements); }, |
| 3907 null); | 3907 null); |
| 3908 } else { | 3908 } else { |
| 3909 handleIf(node, | 3909 handleIf(node, |
| 3910 () { buildTests(labelsAndCases); }, | 3910 () { buildTests(labelsAndCases); }, |
| 3911 () { visitStatementsAndAbort(); }, | 3911 () { visitStatementsAndAbort(); }, |
| 3912 () { buildSwitchCases(cases.tail, expression, | 3912 () { buildSwitchCases(cases.tail, expression, |
| 3913 encounteredCaseTypes); }); | 3913 encounteredCaseTypes); }); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3944 HBasicBlock endFinallyBlock; | 3944 HBasicBlock endFinallyBlock; |
| 3945 | 3945 |
| 3946 startTryBlock = graph.addNewBlock(); | 3946 startTryBlock = graph.addNewBlock(); |
| 3947 open(startTryBlock); | 3947 open(startTryBlock); |
| 3948 visit(node.tryBlock); | 3948 visit(node.tryBlock); |
| 3949 if (!isAborted()) endTryBlock = close(new HGoto()); | 3949 if (!isAborted()) endTryBlock = close(new HGoto()); |
| 3950 SubGraph bodyGraph = new SubGraph(startTryBlock, lastOpenedBlock); | 3950 SubGraph bodyGraph = new SubGraph(startTryBlock, lastOpenedBlock); |
| 3951 SubGraph catchGraph = null; | 3951 SubGraph catchGraph = null; |
| 3952 HParameterValue exception = null; | 3952 HParameterValue exception = null; |
| 3953 | 3953 |
| 3954 if (!node.catchBlocks.isEmpty()) { | 3954 if (!node.catchBlocks.isEmpty) { |
| 3955 localsHandler = new LocalsHandler.from(savedLocals); | 3955 localsHandler = new LocalsHandler.from(savedLocals); |
| 3956 startCatchBlock = graph.addNewBlock(); | 3956 startCatchBlock = graph.addNewBlock(); |
| 3957 open(startCatchBlock); | 3957 open(startCatchBlock); |
| 3958 // Note that the name of this element is irrelevant. | 3958 // Note that the name of this element is irrelevant. |
| 3959 Element element = new Element( | 3959 Element element = new Element( |
| 3960 const SourceString('exception'), ElementKind.PARAMETER, work.element); | 3960 const SourceString('exception'), ElementKind.PARAMETER, work.element); |
| 3961 exception = new HParameterValue(element); | 3961 exception = new HParameterValue(element); |
| 3962 add(exception); | 3962 add(exception); |
| 3963 HInstruction oldRethrowableException = rethrowableException; | 3963 HInstruction oldRethrowableException = rethrowableException; |
| 3964 rethrowableException = exception; | 3964 rethrowableException = exception; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4009 Node trace = catchBlock.trace; | 4009 Node trace = catchBlock.trace; |
| 4010 if (trace != null) { | 4010 if (trace != null) { |
| 4011 pushInvokeHelper1(interceptors.getTraceFromException(), exception); | 4011 pushInvokeHelper1(interceptors.getTraceFromException(), exception); |
| 4012 HInstruction traceInstruction = pop(); | 4012 HInstruction traceInstruction = pop(); |
| 4013 localsHandler.updateLocal(elements[trace], traceInstruction); | 4013 localsHandler.updateLocal(elements[trace], traceInstruction); |
| 4014 } | 4014 } |
| 4015 visit(catchBlock); | 4015 visit(catchBlock); |
| 4016 } | 4016 } |
| 4017 | 4017 |
| 4018 void visitElse() { | 4018 void visitElse() { |
| 4019 if (link.isEmpty()) { | 4019 if (link.isEmpty) { |
| 4020 close(new HThrow(exception, isRethrow: true)); | 4020 close(new HThrow(exception, isRethrow: true)); |
| 4021 } else { | 4021 } else { |
| 4022 CatchBlock newBlock = link.head; | 4022 CatchBlock newBlock = link.head; |
| 4023 handleIf(node, | 4023 handleIf(node, |
| 4024 () { pushCondition(newBlock); }, | 4024 () { pushCondition(newBlock); }, |
| 4025 visitThen, visitElse); | 4025 visitThen, visitElse); |
| 4026 } | 4026 } |
| 4027 } | 4027 } |
| 4028 | 4028 |
| 4029 CatchBlock firstBlock = link.head; | 4029 CatchBlock firstBlock = link.head; |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4444 // } | 4444 // } |
| 4445 // t3 = phi(t2, false); | 4445 // t3 = phi(t2, false); |
| 4446 // } | 4446 // } |
| 4447 // result = phi(t3, false); | 4447 // result = phi(t3, false); |
| 4448 | 4448 |
| 4449 Send send = left.asSend(); | 4449 Send send = left.asSend(); |
| 4450 if (send != null && | 4450 if (send != null && |
| 4451 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) { | 4451 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) { |
| 4452 Node newLeft = send.receiver; | 4452 Node newLeft = send.receiver; |
| 4453 Link<Node> link = send.argumentsNode.nodes; | 4453 Link<Node> link = send.argumentsNode.nodes; |
| 4454 assert(link.tail.isEmpty()); | 4454 assert(link.tail.isEmpty); |
| 4455 Node middle = link.head; | 4455 Node middle = link.head; |
| 4456 handleLogicalAndOrWithLeftNode( | 4456 handleLogicalAndOrWithLeftNode( |
| 4457 newLeft, | 4457 newLeft, |
| 4458 () => handleLogicalAndOrWithLeftNode(middle, visitRight, | 4458 () => handleLogicalAndOrWithLeftNode(middle, visitRight, |
| 4459 isAnd: isAnd), | 4459 isAnd: isAnd), |
| 4460 isAnd: isAnd); | 4460 isAnd: isAnd); |
| 4461 } else { | 4461 } else { |
| 4462 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); | 4462 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); |
| 4463 } | 4463 } |
| 4464 } | 4464 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4486 HPhi phi = | 4486 HPhi phi = |
| 4487 new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue]); | 4487 new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue]); |
| 4488 joinBranch.block.addPhi(phi); | 4488 joinBranch.block.addPhi(phi); |
| 4489 builder.stack.add(phi); | 4489 builder.stack.add(phi); |
| 4490 } | 4490 } |
| 4491 | 4491 |
| 4492 HBasicBlock thenBlock = thenBranch.block; | 4492 HBasicBlock thenBlock = thenBranch.block; |
| 4493 HBasicBlock elseBlock = elseBranch.block; | 4493 HBasicBlock elseBlock = elseBranch.block; |
| 4494 HBasicBlock joinBlock; | 4494 HBasicBlock joinBlock; |
| 4495 // If at least one branch did not abort, open the joinBranch. | 4495 // If at least one branch did not abort, open the joinBranch. |
| 4496 if (!joinBranch.block.predecessors.isEmpty()) { | 4496 if (!joinBranch.block.predecessors.isEmpty) { |
| 4497 startBranch(joinBranch); | 4497 startBranch(joinBranch); |
| 4498 joinBlock = joinBranch.block; | 4498 joinBlock = joinBranch.block; |
| 4499 } | 4499 } |
| 4500 | 4500 |
| 4501 HIfBlockInformation info = | 4501 HIfBlockInformation info = |
| 4502 new HIfBlockInformation( | 4502 new HIfBlockInformation( |
| 4503 new HSubExpressionBlockInformation(conditionBranch.graph), | 4503 new HSubExpressionBlockInformation(conditionBranch.graph), |
| 4504 new HSubGraphBlockInformation(thenBranch.graph), | 4504 new HSubGraphBlockInformation(thenBranch.graph), |
| 4505 new HSubGraphBlockInformation(elseBranch.graph)); | 4505 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4506 | 4506 |
| 4507 HBasicBlock conditionStartBlock = conditionBranch.block; | 4507 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4508 conditionStartBlock.setBlockFlow(info, joinBlock); | 4508 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4509 SubGraph conditionGraph = conditionBranch.graph; | 4509 SubGraph conditionGraph = conditionBranch.graph; |
| 4510 HIf branch = conditionGraph.end.last; | 4510 HIf branch = conditionGraph.end.last; |
| 4511 assert(branch is HIf); | 4511 assert(branch is HIf); |
| 4512 branch.blockInformation = conditionStartBlock.blockFlow; | 4512 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4513 } | 4513 } |
| 4514 } | 4514 } |
| OLD | NEW |