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

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

Issue 11238035: Make isEmpty a getter. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update status file with co19 issue number. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/bailout.dart ('k') | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698