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 |