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

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

Issue 11364134: Merge libv1. (Closed) Base URL: https://dart.googlecode.com/svn/experimental/lib_v2/dart
Patch Set: Reupload due to error Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of ssa; 5 part of ssa;
6 6
7 class Interceptors { 7 class Interceptors {
8 Compiler compiler; 8 Compiler compiler;
9 Interceptors(Compiler this.compiler); 9 Interceptors(Compiler this.compiler);
10 10
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 void enterScope(Node node, Element element) { 325 void enterScope(Node node, Element element) {
326 // See if any variable in the top-scope of the function is captured. If yes 326 // See if any variable in the top-scope of the function is captured. If yes
327 // we need to create a box-object. 327 // we need to create a box-object.
328 ClosureScope scopeData = closureData.capturingScopes[node]; 328 ClosureScope scopeData = closureData.capturingScopes[node];
329 if (scopeData != null) { 329 if (scopeData != null) {
330 HInstruction box; 330 HInstruction box;
331 // The scope has captured variables. 331 // The scope has captured variables.
332 if (element != null && element.isGenerativeConstructorBody()) { 332 if (element != null && element.isGenerativeConstructorBody()) {
333 // The box is passed as a parameter to a generative 333 // The box is passed as a parameter to a generative
334 // constructor body. 334 // constructor body.
335 box = new HParameterValue(scopeData.boxElement); 335 box = builder.addParameter(scopeData.boxElement);
336 builder.add(box);
337 } else { 336 } else {
338 box = createBox(); 337 box = createBox();
339 } 338 }
340 // Add the box to the known locals. 339 // Add the box to the known locals.
341 directLocals[scopeData.boxElement] = box; 340 directLocals[scopeData.boxElement] = box;
342 // Make sure that accesses to the boxed locals go into the box. We also 341 // Make sure that accesses to the boxed locals go into the box. We also
343 // need to make sure that parameters are copied into the box if necessary. 342 // need to make sure that parameters are copied into the box if necessary.
344 scopeData.capturedVariableMapping.forEach((Element from, Element to) { 343 scopeData.capturedVariableMapping.forEach((Element from, Element to) {
345 // The [from] can only be a parameter for function-scopes and not 344 // The [from] can only be a parameter for function-scopes and not
346 // loop scopes. 345 // loop scopes.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 void startFunction(Element element, Expression node) { 386 void startFunction(Element element, Expression node) {
388 assert(invariant(node, element.isImplementation)); 387 assert(invariant(node, element.isImplementation));
389 Compiler compiler = builder.compiler; 388 Compiler compiler = builder.compiler;
390 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( 389 closureData = compiler.closureToClassMapper.computeClosureToClassMapping(
391 element, node, builder.elements); 390 element, node, builder.elements);
392 391
393 if (element is FunctionElement) { 392 if (element is FunctionElement) {
394 FunctionElement functionElement = element; 393 FunctionElement functionElement = element;
395 FunctionSignature params = functionElement.computeSignature(compiler); 394 FunctionSignature params = functionElement.computeSignature(compiler);
396 params.orderedForEachParameter((Element parameterElement) { 395 params.orderedForEachParameter((Element parameterElement) {
397 HInstruction parameter = new HParameterValue(parameterElement); 396 HInstruction parameter = builder.addParameter(parameterElement);
398 builder.add(parameter);
399 builder.parameters[parameterElement] = parameter; 397 builder.parameters[parameterElement] = parameter;
400 directLocals[parameterElement] = parameter; 398 directLocals[parameterElement] = parameter;
401 parameter.guaranteedType = 399 parameter.guaranteedType =
402 builder.mapInferredType( 400 builder.mapInferredType(
403 typesTask.getGuaranteedTypeOfElement(parameterElement)); 401 typesTask.getGuaranteedTypeOfElement(parameterElement));
404 }); 402 });
405 } 403 }
406 404
407 enterScope(node, element); 405 enterScope(node, element);
408 406
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 // In all other cases a new box will be created when entering the body of 656 // In all other cases a new box will be created when entering the body of
659 // the next iteration. 657 // the next iteration.
660 ClosureScope scopeData = closureData.capturingScopes[node]; 658 ClosureScope scopeData = closureData.capturingScopes[node];
661 if (scopeData == null) return; 659 if (scopeData == null) return;
662 if (scopeData.hasBoxedLoopVariables()) { 660 if (scopeData.hasBoxedLoopVariables()) {
663 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables); 661 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables);
664 } 662 }
665 } 663 }
666 664
667 void endLoop(HBasicBlock loopEntry) { 665 void endLoop(HBasicBlock loopEntry) {
666 // If the loop has an aborting body, we don't update the loop
667 // phis.
668 if (loopEntry.predecessors.length == 1) return;
668 loopEntry.forEachPhi((HPhi phi) { 669 loopEntry.forEachPhi((HPhi phi) {
669 Element element = phi.sourceElement; 670 Element element = phi.sourceElement;
670 HInstruction postLoopDefinition = directLocals[element]; 671 HInstruction postLoopDefinition = directLocals[element];
671 phi.addInput(postLoopDefinition); 672 phi.addInput(postLoopDefinition);
672 }); 673 });
673 } 674 }
674 675
675 /** 676 /**
676 * Merge [otherLocals] into this locals handler, creating phi-nodes when 677 * Merge [otherLocals] into this locals handler, creating phi-nodes when
677 * there is a conflict. 678 * there is a conflict.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 761
761 abstract class JumpHandler { 762 abstract class JumpHandler {
762 factory JumpHandler(SsaBuilder builder, TargetElement target) { 763 factory JumpHandler(SsaBuilder builder, TargetElement target) {
763 return new TargetJumpHandler(builder, target); 764 return new TargetJumpHandler(builder, target);
764 } 765 }
765 void generateBreak([LabelElement label]); 766 void generateBreak([LabelElement label]);
766 void generateContinue([LabelElement label]); 767 void generateContinue([LabelElement label]);
767 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); 768 void forEachBreak(void action(HBreak instruction, LocalsHandler locals));
768 void forEachContinue(void action(HContinue instruction, 769 void forEachContinue(void action(HContinue instruction,
769 LocalsHandler locals)); 770 LocalsHandler locals));
771 bool hasAnyContinue();
772 bool hasAnyBreak();
770 void close(); 773 void close();
771 final TargetElement target; 774 final TargetElement target;
772 List<LabelElement> labels(); 775 List<LabelElement> labels();
773 } 776 }
774 777
775 // Insert break handler used to avoid null checks when a target isn't 778 // Insert break handler used to avoid null checks when a target isn't
776 // used as the target of a break, and therefore doesn't need a break 779 // used as the target of a break, and therefore doesn't need a break
777 // handler associated with it. 780 // handler associated with it.
778 class NullJumpHandler implements JumpHandler { 781 class NullJumpHandler implements JumpHandler {
779 final Compiler compiler; 782 final Compiler compiler;
780 783
781 NullJumpHandler(this.compiler); 784 NullJumpHandler(this.compiler);
782 785
783 void generateBreak([LabelElement label]) { 786 void generateBreak([LabelElement label]) {
784 compiler.internalError('generateBreak should not be called'); 787 compiler.internalError('generateBreak should not be called');
785 } 788 }
786 789
787 void generateContinue([LabelElement label]) { 790 void generateContinue([LabelElement label]) {
788 compiler.internalError('generateContinue should not be called'); 791 compiler.internalError('generateContinue should not be called');
789 } 792 }
790 793
791 void forEachBreak(Function ignored) { } 794 void forEachBreak(Function ignored) { }
792 void forEachContinue(Function ignored) { } 795 void forEachContinue(Function ignored) { }
793 void close() { } 796 void close() { }
797 bool hasAnyContinue() => false;
798 bool hasAnyBreak() => false;
794 799
795 List<LabelElement> labels() => const <LabelElement>[]; 800 List<LabelElement> labels() => const <LabelElement>[];
796 TargetElement get target => null; 801 TargetElement get target => null;
797 } 802 }
798 803
799 // Records breaks until a target block is available. 804 // Records breaks until a target block is available.
800 // Breaks are always forward jumps. 805 // Breaks are always forward jumps.
801 // Continues in loops are implemented as breaks of the body. 806 // Continues in loops are implemented as breaks of the body.
802 // Continues in switches is currently not handled. 807 // Continues in switches is currently not handled.
803 class TargetJumpHandler implements JumpHandler { 808 class TargetJumpHandler implements JumpHandler {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 if (entry.isBreak()) action(entry.jumpInstruction, entry.locals); 846 if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
842 } 847 }
843 } 848 }
844 849
845 void forEachContinue(Function action) { 850 void forEachContinue(Function action) {
846 for (JumpHandlerEntry entry in jumps) { 851 for (JumpHandlerEntry entry in jumps) {
847 if (entry.isContinue()) action(entry.jumpInstruction, entry.locals); 852 if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
848 } 853 }
849 } 854 }
850 855
856 bool hasAnyContinue() {
857 for (JumpHandlerEntry entry in jumps) {
858 if (entry.isContinue()) return true;
859 }
860 return false;
861 }
862
863 bool hasAnyBreak() {
864 for (JumpHandlerEntry entry in jumps) {
865 if (entry.isBreak()) return true;
866 }
867 return false;
868 }
869
851 void close() { 870 void close() {
852 // The mapping from TargetElement to JumpHandler is no longer needed. 871 // The mapping from TargetElement to JumpHandler is no longer needed.
853 builder.jumpTargets.remove(target); 872 builder.jumpTargets.remove(target);
854 } 873 }
855 874
856 List<LabelElement> labels() { 875 List<LabelElement> labels() {
857 List<LabelElement> result = null; 876 List<LabelElement> result = null;
858 for (LabelElement element in target.labels) { 877 for (LabelElement element in target.labels) {
859 if (result == null) result = <LabelElement>[]; 878 if (result == null) result = <LabelElement>[];
860 result.add(element); 879 result.add(element);
861 } 880 }
862 return (result == null) ? const <LabelElement>[] : result; 881 return (result == null) ? const <LabelElement>[] : result;
863 } 882 }
864 } 883 }
865 884
866 class SsaBuilder extends ResolvedVisitor implements Visitor { 885 class SsaBuilder extends ResolvedVisitor implements Visitor {
867 final SsaBuilderTask builder; 886 final SsaBuilderTask builder;
868 final JavaScriptBackend backend; 887 final JavaScriptBackend backend;
869 final Interceptors interceptors; 888 final Interceptors interceptors;
870 final WorkItem work; 889 final WorkItem work;
871 final ConstantSystem constantSystem; 890 final ConstantSystem constantSystem;
872 bool methodInterceptionEnabled; 891 bool methodInterceptionEnabled;
873 HGraph graph; 892 HGraph graph;
874 LocalsHandler localsHandler; 893 LocalsHandler localsHandler;
875 HInstruction rethrowableException; 894 HInstruction rethrowableException;
876 Map<Element, HInstruction> parameters; 895 Map<Element, HInstruction> parameters;
877 final RuntimeTypeInformation rti; 896 final RuntimeTypeInformation rti;
897 HParameterValue lastAddedParameter;
878 898
879 Map<TargetElement, JumpHandler> jumpTargets; 899 Map<TargetElement, JumpHandler> jumpTargets;
880 900
881 /** 901 /**
882 * Variables stored in the current activation. These variables are 902 * Variables stored in the current activation. These variables are
883 * being updated in try/catch blocks, and should be 903 * being updated in try/catch blocks, and should be
884 * accessed indirectly through [HLocalGet] and [HLocalSet]. 904 * accessed indirectly through [HLocalGet] and [HLocalSet].
885 */ 905 */
886 Map<Element, HLocalValue> activationVariables; 906 Map<Element, HLocalValue> activationVariables;
887 907
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 rti = builder.compiler.codegenWorld.rti, 939 rti = builder.compiler.codegenWorld.rti,
920 super(work.resolutionTree) { 940 super(work.resolutionTree) {
921 localsHandler = new LocalsHandler(this); 941 localsHandler = new LocalsHandler(this);
922 } 942 }
923 943
924 static const MAX_INLINING_DEPTH = 3; 944 static const MAX_INLINING_DEPTH = 3;
925 static const MAX_INLINING_SOURCE_SIZE = 128; 945 static const MAX_INLINING_SOURCE_SIZE = 128;
926 List<InliningState> inliningStack; 946 List<InliningState> inliningStack;
927 Element returnElement; 947 Element returnElement;
928 DartType returnType; 948 DartType returnType;
949 bool inTryStatement = false;
929 950
930 void disableMethodInterception() { 951 void disableMethodInterception() {
931 assert(methodInterceptionEnabled); 952 assert(methodInterceptionEnabled);
932 methodInterceptionEnabled = false; 953 methodInterceptionEnabled = false;
933 } 954 }
934 955
935 void enableMethodInterception() { 956 void enableMethodInterception() {
936 assert(!methodInterceptionEnabled); 957 assert(!methodInterceptionEnabled);
937 methodInterceptionEnabled = true; 958 methodInterceptionEnabled = true;
938 } 959 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1010 classElement.origin.backendMembers = 1031 classElement.origin.backendMembers =
1011 classElement.origin.backendMembers.prepend(bodyElement.origin); 1032 classElement.origin.backendMembers.prepend(bodyElement.origin);
1012 } 1033 }
1013 compiler.enqueuer.codegen.addToWorkList(bodyElement.declaration, 1034 compiler.enqueuer.codegen.addToWorkList(bodyElement.declaration,
1014 treeElements); 1035 treeElements);
1015 } 1036 }
1016 assert(bodyElement.isGenerativeConstructorBody()); 1037 assert(bodyElement.isGenerativeConstructorBody());
1017 return bodyElement; 1038 return bodyElement;
1018 } 1039 }
1019 1040
1041 HParameterValue addParameter(Element element) {
1042 HParameterValue result = new HParameterValue(element);
1043 if (lastAddedParameter == null) {
1044 graph.entry.addBefore(graph.entry.first, result);
1045 } else {
1046 graph.entry.addAfter(lastAddedParameter, result);
1047 }
1048 lastAddedParameter = result;
1049 return result;
1050 }
1051
1020 /** 1052 /**
1021 * Documentation wanted -- johnniwinther 1053 * Documentation wanted -- johnniwinther
1022 * 1054 *
1023 * Invariant: [function] must be an implementation element. 1055 * Invariant: [function] must be an implementation element.
1024 */ 1056 */
1025 InliningState enterInlinedMethod(PartialFunctionElement function, 1057 InliningState enterInlinedMethod(PartialFunctionElement function,
1026 Selector selector, 1058 Selector selector,
1027 Link<Node> arguments) { 1059 Link<Node> arguments) {
1028 assert(invariant(function, function.isImplementation)); 1060 assert(invariant(function, function.isImplementation));
1029 1061
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 return closeFunction(); 1460 return closeFunction();
1429 } 1461 }
1430 1462
1431 void addParameterCheckInstruction(Element element) { 1463 void addParameterCheckInstruction(Element element) {
1432 HInstruction check; 1464 HInstruction check;
1433 Element checkResultElement = 1465 Element checkResultElement =
1434 localsHandler.closureData.parametersWithSentinel[element]; 1466 localsHandler.closureData.parametersWithSentinel[element];
1435 if (currentElement.isGenerativeConstructorBody()) { 1467 if (currentElement.isGenerativeConstructorBody()) {
1436 // A generative constructor body receives extra parameters that 1468 // A generative constructor body receives extra parameters that
1437 // indicate if a parameter was passed to the factory. 1469 // indicate if a parameter was passed to the factory.
1438 check = new HParameterValue(checkResultElement); 1470 check = addParameter(checkResultElement);
1439 add(check);
1440 } else { 1471 } else {
1441 // This is the code we emit for a parameter that is being checked 1472 // This is the code we emit for a parameter that is being checked
1442 // on whether it was given at value at the call site: 1473 // on whether it was given at value at the call site:
1443 // 1474 //
1444 // foo([a = 42) { 1475 // foo([a = 42) {
1445 // if (?a) print('parameter passed $a'); 1476 // if (?a) print('parameter passed $a');
1446 // } 1477 // }
1447 // 1478 //
1448 // foo([a = 42]) { 1479 // foo([a = 42]) {
1449 // var t1 = a === sentinel; 1480 // var t1 = a === sentinel;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1521 } else { 1552 } else {
1522 // Otherwise it is a lazy initializer which does not have parameters. 1553 // Otherwise it is a lazy initializer which does not have parameters.
1523 assert(element is VariableElement); 1554 assert(element is VariableElement);
1524 } 1555 }
1525 1556
1526 // Add the type parameters of the class as parameters of this 1557 // Add the type parameters of the class as parameters of this
1527 // method. 1558 // method.
1528 var enclosing = element.enclosingElement; 1559 var enclosing = element.enclosingElement;
1529 if (element.isConstructor() && compiler.world.needsRti(enclosing)) { 1560 if (element.isConstructor() && compiler.world.needsRti(enclosing)) {
1530 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { 1561 enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
1531 HParameterValue param = new HParameterValue(typeVariable.element); 1562 HParameterValue param = addParameter(typeVariable.element);
1532 add(param);
1533 localsHandler.directLocals[typeVariable.element] = param; 1563 localsHandler.directLocals[typeVariable.element] = param;
1534 }); 1564 });
1535 } 1565 }
1536 } 1566 }
1537 1567
1538 HInstruction potentiallyCheckType( 1568 HInstruction potentiallyCheckType(
1539 HInstruction original, DartType type, 1569 HInstruction original, DartType type,
1540 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { 1570 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
1541 if (!compiler.enableTypeAssertions) return original; 1571 if (!compiler.enableTypeAssertions) return original;
1542 HInstruction other = original.convertType(compiler, type, kind); 1572 HInstruction other = original.convertType(compiler, type, kind);
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 /** 1738 /**
1709 * Ends the loop: 1739 * Ends the loop:
1710 * - creates a new block and adds it as successor to the [branchBlock]. 1740 * - creates a new block and adds it as successor to the [branchBlock].
1711 * - opens the new block (setting as [current]). 1741 * - opens the new block (setting as [current]).
1712 * - notifies the locals handler that we're exiting a loop. 1742 * - notifies the locals handler that we're exiting a loop.
1713 */ 1743 */
1714 void endLoop(HBasicBlock loopEntry, 1744 void endLoop(HBasicBlock loopEntry,
1715 HBasicBlock branchBlock, 1745 HBasicBlock branchBlock,
1716 JumpHandler jumpHandler, 1746 JumpHandler jumpHandler,
1717 LocalsHandler savedLocals) { 1747 LocalsHandler savedLocals) {
1748 if (branchBlock == null && !jumpHandler.hasAnyBreak()) return;
1749
1718 HBasicBlock loopExitBlock = addNewBlock(); 1750 HBasicBlock loopExitBlock = addNewBlock();
1719 assert(branchBlock.successors.length == 1); 1751 assert(branchBlock == null || branchBlock.successors.length == 1);
1720 List<LocalsHandler> breakLocals = <LocalsHandler>[]; 1752 List<LocalsHandler> breakLocals = <LocalsHandler>[];
1721 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { 1753 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
1722 breakInstruction.block.addSuccessor(loopExitBlock); 1754 breakInstruction.block.addSuccessor(loopExitBlock);
1723 breakLocals.add(locals); 1755 breakLocals.add(locals);
1724 }); 1756 });
1725 branchBlock.addSuccessor(loopExitBlock); 1757 if (branchBlock != null) {
1758 branchBlock.addSuccessor(loopExitBlock);
1759 }
1726 open(loopExitBlock); 1760 open(loopExitBlock);
1727 localsHandler.endLoop(loopEntry); 1761 localsHandler.endLoop(loopEntry);
1728 if (!breakLocals.isEmpty) { 1762 if (!breakLocals.isEmpty) {
1729 breakLocals.add(savedLocals); 1763 breakLocals.add(savedLocals);
1730 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock); 1764 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock);
1731 } else { 1765 } else {
1732 localsHandler = savedLocals; 1766 localsHandler = savedLocals;
1733 } 1767 }
1734 } 1768 }
1735 1769
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1786 new SubExpression(conditionBlock, conditionExitBlock); 1820 new SubExpression(conditionBlock, conditionExitBlock);
1787 1821
1788 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 1822 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
1789 1823
1790 // The body. 1824 // The body.
1791 HBasicBlock beginBodyBlock = addNewBlock(); 1825 HBasicBlock beginBodyBlock = addNewBlock();
1792 conditionExitBlock.addSuccessor(beginBodyBlock); 1826 conditionExitBlock.addSuccessor(beginBodyBlock);
1793 open(beginBodyBlock); 1827 open(beginBodyBlock);
1794 1828
1795 localsHandler.enterLoopBody(loop); 1829 localsHandler.enterLoopBody(loop);
1796 hackAroundPossiblyAbortingBody(loop, body); 1830 body();
1797 1831
1798 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); 1832 SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock);
1799 HBasicBlock bodyBlock = close(new HGoto()); 1833 HBasicBlock bodyBlock = current;
1834 if (current != null) close(new HGoto());
1800 1835
1801 // Update. 1836 SubExpression updateGraph;
1802 // We create an update block, even when we are in a while loop. There the
1803 // update block is the jump-target for continue statements. We could avoid
1804 // the creation if there is no continue, but for now we always create it.
1805 HBasicBlock updateBlock = addNewBlock();
1806 1837
1807 List<LocalsHandler> continueLocals = <LocalsHandler>[]; 1838 // Check that the loop has at least one back-edge.
1808 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { 1839 if (jumpHandler.hasAnyContinue() || bodyBlock != null) {
1809 instruction.block.addSuccessor(updateBlock); 1840 // Update.
1810 continueLocals.add(locals); 1841 // We create an update block, even when we are in a while loop. There the
1811 }); 1842 // update block is the jump-target for continue statements. We could avoid
1812 bodyBlock.addSuccessor(updateBlock); 1843 // the creation if there is no continue, but for now we always create it.
1813 continueLocals.add(localsHandler); 1844 HBasicBlock updateBlock = addNewBlock();
1814 1845
1815 open(updateBlock); 1846 List<LocalsHandler> continueLocals = <LocalsHandler>[];
1847 jumpHandler.forEachContinue((HContinue instruction,
1848 LocalsHandler locals) {
1849 instruction.block.addSuccessor(updateBlock);
1850 continueLocals.add(locals);
1851 });
1816 1852
1817 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock);
1818 1853
1819 HLabeledBlockInformation labelInfo; 1854 if (bodyBlock != null) {
1820 List<LabelElement> labels = jumpHandler.labels(); 1855 continueLocals.add(localsHandler);
1821 TargetElement target = elements[loop]; 1856 bodyBlock.addSuccessor(updateBlock);
1822 if (!labels.isEmpty) { 1857 }
1823 beginBodyBlock.setBlockFlow( 1858
1824 new HLabeledBlockInformation( 1859 open(updateBlock);
1825 new HSubGraphBlockInformation(bodyGraph), 1860 localsHandler =
1826 jumpHandler.labels(), 1861 continueLocals[0].mergeMultiple(continueLocals, updateBlock);
1827 isContinue: true), 1862
1828 updateBlock); 1863 HLabeledBlockInformation labelInfo;
1829 } else if (target != null && target.isContinueTarget) { 1864 List<LabelElement> labels = jumpHandler.labels();
1830 beginBodyBlock.setBlockFlow( 1865 TargetElement target = elements[loop];
1831 new HLabeledBlockInformation.implicit( 1866 if (!labels.isEmpty) {
1832 new HSubGraphBlockInformation(bodyGraph), 1867 beginBodyBlock.setBlockFlow(
1833 target, 1868 new HLabeledBlockInformation(
1834 isContinue: true), 1869 new HSubGraphBlockInformation(bodyGraph),
1835 updateBlock); 1870 jumpHandler.labels(),
1871 isContinue: true),
1872 updateBlock);
1873 } else if (target != null && target.isContinueTarget) {
1874 beginBodyBlock.setBlockFlow(
1875 new HLabeledBlockInformation.implicit(
1876 new HSubGraphBlockInformation(bodyGraph),
1877 target,
1878 isContinue: true),
1879 updateBlock);
1880 }
1881
1882 localsHandler.enterLoopUpdates(loop);
1883
1884 update();
1885
1886 HBasicBlock updateEndBlock = close(new HGoto());
1887 // The back-edge completing the cycle.
1888 updateEndBlock.addSuccessor(conditionBlock);
1889 updateGraph = new SubExpression(updateBlock, updateEndBlock);
1836 } 1890 }
1837 1891
1838 localsHandler.enterLoopUpdates(loop);
1839
1840 update();
1841
1842 HBasicBlock updateEndBlock = close(new HGoto());
1843 // The back-edge completing the cycle.
1844 updateEndBlock.addSuccessor(conditionBlock);
1845 conditionBlock.postProcessLoopHeader(); 1892 conditionBlock.postProcessLoopHeader();
1846 SubExpression updateGraph = new SubExpression(updateBlock, updateEndBlock);
1847 1893
1848 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); 1894 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
1849 HLoopBlockInformation info = 1895 HLoopBlockInformation info =
1850 new HLoopBlockInformation( 1896 new HLoopBlockInformation(
1851 HLoopBlockInformation.loopType(loop), 1897 HLoopBlockInformation.loopType(loop),
1852 wrapExpressionGraph(initializerGraph), 1898 wrapExpressionGraph(initializerGraph),
1853 wrapExpressionGraph(conditionExpression), 1899 wrapExpressionGraph(conditionExpression),
1854 wrapStatementGraph(bodyGraph), 1900 wrapStatementGraph(bodyGraph),
1855 wrapExpressionGraph(updateGraph), 1901 wrapExpressionGraph(updateGraph),
1856 conditionBlock.loopInformation.target, 1902 conditionBlock.loopInformation.target,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1921 // Add extra block to hang labels on. 1967 // Add extra block to hang labels on.
1922 // It doesn't currently work if they are on the same block as the 1968 // It doesn't currently work if they are on the same block as the
1923 // HLoopInfo. The handling of HLabeledBlockInformation will visit a 1969 // HLoopInfo. The handling of HLabeledBlockInformation will visit a
1924 // SubGraph that starts at the same block again, so the HLoopInfo is 1970 // SubGraph that starts at the same block again, so the HLoopInfo is
1925 // either handled twice, or it's handled after the labeled block info, 1971 // either handled twice, or it's handled after the labeled block info,
1926 // both of which generate the wrong code. 1972 // both of which generate the wrong code.
1927 // Using a separate block is just a simple workaround. 1973 // Using a separate block is just a simple workaround.
1928 bodyEntryBlock = openNewBlock(); 1974 bodyEntryBlock = openNewBlock();
1929 } 1975 }
1930 localsHandler.enterLoopBody(node); 1976 localsHandler.enterLoopBody(node);
1931 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); 1977 visit(node.body);
1932 1978
1933 // If there are no continues we could avoid the creation of the condition 1979 // If there are no continues we could avoid the creation of the condition
1934 // block. This could also lead to a block having multiple entries and exits. 1980 // block. This could also lead to a block having multiple entries and exits.
1935 HBasicBlock bodyExitBlock = close(new HGoto()); 1981 HBasicBlock bodyExitBlock;
1936 HBasicBlock conditionBlock = addNewBlock(); 1982 bool isAbortingBody = false;
1983 if (current != null) {
1984 bodyExitBlock = close(new HGoto());
1985 } else {
1986 isAbortingBody = true;
1987 bodyExitBlock = lastOpenedBlock;
1988 }
1937 1989
1938 List<LocalsHandler> continueLocals = <LocalsHandler>[]; 1990 SubExpression conditionExpression;
1939 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { 1991 HBasicBlock conditionEndBlock;
1940 instruction.block.addSuccessor(conditionBlock); 1992 if (!isAbortingBody || hasContinues) {
1941 continueLocals.add(locals); 1993 HBasicBlock conditionBlock = addNewBlock();
1942 }); 1994
1943 bodyExitBlock.addSuccessor(conditionBlock); 1995 List<LocalsHandler> continueLocals = <LocalsHandler>[];
1944 if (!continueLocals.isEmpty) { 1996 jumpHandler.forEachContinue((HContinue instruction,
1945 continueLocals.add(localsHandler); 1997 LocalsHandler locals) {
1946 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); 1998 instruction.block.addSuccessor(conditionBlock);
1947 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); 1999 continueLocals.add(locals);
1948 List<LabelElement> labels = jumpHandler.labels(); 2000 });
1949 HSubGraphBlockInformation bodyInfo = 2001
1950 new HSubGraphBlockInformation(bodyGraph); 2002 if (!isAbortingBody) {
1951 HLabeledBlockInformation info; 2003 bodyExitBlock.addSuccessor(conditionBlock);
1952 if (!labels.isEmpty) {
1953 info = new HLabeledBlockInformation(bodyInfo, labels, isContinue: true);
1954 } else {
1955 info = new HLabeledBlockInformation.implicit(bodyInfo, target,
1956 isContinue: true);
1957 } 2004 }
1958 bodyEntryBlock.setBlockFlow(info, conditionBlock); 2005
2006 if (!continueLocals.isEmpty) {
2007 if (!isAbortingBody) continueLocals.add(localsHandler);
2008 localsHandler =
2009 savedLocals.mergeMultiple(continueLocals, conditionBlock);
2010 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
2011 List<LabelElement> labels = jumpHandler.labels();
2012 HSubGraphBlockInformation bodyInfo =
2013 new HSubGraphBlockInformation(bodyGraph);
2014 HLabeledBlockInformation info;
2015 if (!labels.isEmpty) {
2016 info = new HLabeledBlockInformation(bodyInfo, labels,
2017 isContinue: true);
2018 } else {
2019 info = new HLabeledBlockInformation.implicit(bodyInfo, target,
2020 isContinue: true);
2021 }
2022 bodyEntryBlock.setBlockFlow(info, conditionBlock);
2023 }
2024 open(conditionBlock);
2025
2026 visit(node.condition);
2027 assert(!isAborted());
2028 HInstruction conditionInstruction = popBoolified();
2029 conditionEndBlock = close(
2030 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
2031
2032 conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge.
2033 conditionExpression =
2034 new SubExpression(conditionBlock, conditionEndBlock);
1959 } 2035 }
1960 open(conditionBlock);
1961 2036
1962 visit(node.condition);
1963 assert(!isAborted());
1964 HInstruction conditionInstruction = popBoolified();
1965 HBasicBlock conditionEndBlock =
1966 close(new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
1967
1968 conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge.
1969 loopEntryBlock.postProcessLoopHeader(); 2037 loopEntryBlock.postProcessLoopHeader();
1970 2038
1971 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); 2039 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler);
1972 jumpHandler.close(); 2040 jumpHandler.close();
1973 2041
1974 SubExpression conditionExpression =
1975 new SubExpression(conditionBlock, conditionEndBlock);
1976 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); 2042 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
1977 2043
1978 HLoopBlockInformation loopBlockInfo = 2044 HLoopBlockInformation loopBlockInfo =
1979 new HLoopBlockInformation( 2045 new HLoopBlockInformation(
1980 HLoopBlockInformation.DO_WHILE_LOOP, 2046 HLoopBlockInformation.DO_WHILE_LOOP,
1981 null, 2047 null,
1982 wrapExpressionGraph(conditionExpression), 2048 wrapExpressionGraph(conditionExpression),
1983 wrapStatementGraph(bodyGraph), 2049 wrapStatementGraph(bodyGraph),
1984 null, 2050 null,
1985 loopEntryBlock.loopInformation.target, 2051 loopEntryBlock.loopInformation.target,
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
2191 HInstruction generateInstanceSendReceiver(Send send) { 2257 HInstruction generateInstanceSendReceiver(Send send) {
2192 assert(Elements.isInstanceSend(send, elements)); 2258 assert(Elements.isInstanceSend(send, elements));
2193 if (send.receiver == null) { 2259 if (send.receiver == null) {
2194 return localsHandler.readThis(); 2260 return localsHandler.readThis();
2195 } 2261 }
2196 visit(send.receiver); 2262 visit(send.receiver);
2197 return pop(); 2263 return pop();
2198 } 2264 }
2199 2265
2200 String getTargetName(ErroneousElement error, [String prefix]) { 2266 String getTargetName(ErroneousElement error, [String prefix]) {
2201 String result = error.targetName.slowToString(); 2267 String result = error.name.slowToString();
2202 if (?prefix) { 2268 if (?prefix) {
2203 result = '$prefix $result'; 2269 result = '$prefix $result';
2204 } 2270 }
2205 return result; 2271 return result;
2206 } 2272 }
2207 2273
2208 void generateInstanceGetterWithCompiledReceiver(Send send, 2274 void generateInstanceGetterWithCompiledReceiver(Send send,
2209 HInstruction receiver) { 2275 HInstruction receiver) {
2210 assert(Elements.isInstanceSend(send, elements)); 2276 assert(Elements.isInstanceSend(send, elements));
2211 // TODO(kasperl): This is a convoluted way of checking if we're 2277 // TODO(kasperl): This is a convoluted way of checking if we're
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
3000 return HType.UNKNOWN; 3066 return HType.UNKNOWN;
3001 } 3067 }
3002 } 3068 }
3003 3069
3004 Element constructor = elements[node]; 3070 Element constructor = elements[node];
3005 Selector selector = elements.getSelector(node); 3071 Selector selector = elements.getSelector(node);
3006 if (compiler.enqueuer.resolution.getCachedElements(constructor) == null) { 3072 if (compiler.enqueuer.resolution.getCachedElements(constructor) == null) {
3007 compiler.internalError("Unresolved element: $constructor", node: node); 3073 compiler.internalError("Unresolved element: $constructor", node: node);
3008 } 3074 }
3009 FunctionElement functionElement = constructor; 3075 FunctionElement functionElement = constructor;
3010 constructor = functionElement.defaultImplementation; 3076 constructor = functionElement.redirectionTarget;
3011 // TODO(5346): Try to avoid the need for calling [declaration] before 3077 // TODO(5346): Try to avoid the need for calling [declaration] before
3012 // creating an [HStatic]. 3078 // creating an [HStatic].
3013 HInstruction target = new HStatic(constructor.declaration); 3079 HInstruction target = new HStatic(constructor.declaration);
3014 add(target); 3080 add(target);
3015 var inputs = <HInstruction>[]; 3081 var inputs = <HInstruction>[];
3016 inputs.add(target); 3082 inputs.add(target);
3017 // TODO(5347): Try to avoid the need for calling [implementation] before 3083 // TODO(5347): Try to avoid the need for calling [implementation] before
3018 // calling [addStaticSendArgumentsToList]. 3084 // calling [addStaticSendArgumentsToList].
3019 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 3085 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
3020 constructor.implementation, 3086 constructor.implementation,
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
3234 existingArguments.add(parameter.name.slowToString()); 3300 existingArguments.add(parameter.name.slowToString());
3235 }); 3301 });
3236 generateThrowNoSuchMethod(diagnosticNode, 3302 generateThrowNoSuchMethod(diagnosticNode,
3237 function.name.slowToString(), 3303 function.name.slowToString(),
3238 argumentNodes: argumentNodes, 3304 argumentNodes: argumentNodes,
3239 existingArguments: existingArguments); 3305 existingArguments: existingArguments);
3240 } 3306 }
3241 3307
3242 visitNewExpression(NewExpression node) { 3308 visitNewExpression(NewExpression node) {
3243 Element element = elements[node.send]; 3309 Element element = elements[node.send];
3310 if (!Elements.isErroneousElement(element)) {
3311 element = element.redirectionTarget;
3312 }
3244 if (Elements.isErroneousElement(element)) { 3313 if (Elements.isErroneousElement(element)) {
3245 ErroneousElement error = element; 3314 ErroneousElement error = element;
3246 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { 3315 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR) {
3247 generateThrowNoSuchMethod(node.send, 3316 generateThrowNoSuchMethod(node.send,
3248 getTargetName(error, 'constructor'), 3317 getTargetName(error, 'constructor'),
3249 argumentNodes: node.send.arguments); 3318 argumentNodes: node.send.arguments);
3250 } else if (error.messageKind == MessageKind.CANNOT_RESOLVE) { 3319 } else if (error.messageKind == MessageKind.CANNOT_RESOLVE) {
3251 Message message = error.messageKind.message(error.messageArguments); 3320 Message message = error.messageKind.message(error.messageArguments);
3252 generateRuntimeError(node.send, message.toString()); 3321 generateRuntimeError(node.send, message.toString());
3253 } else { 3322 } else {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
3437 visit(node.expression); 3506 visit(node.expression);
3438 // Remove the result and reveal the duplicated receiver on the stack. 3507 // Remove the result and reveal the duplicated receiver on the stack.
3439 pop(); 3508 pop();
3440 } 3509 }
3441 3510
3442 visitCascadeReceiver(CascadeReceiver node) { 3511 visitCascadeReceiver(CascadeReceiver node) {
3443 visit(node.expression); 3512 visit(node.expression);
3444 dup(); 3513 dup();
3445 } 3514 }
3446 3515
3516 void handleInTryStatement() {
3517 if (!inTryStatement) return;
3518 HBasicBlock block = close(new HExitTry());
3519 HBasicBlock newBlock = graph.addNewBlock();
3520 block.addSuccessor(newBlock);
3521 open(newBlock);
3522 }
3523
3447 visitReturn(Return node) { 3524 visitReturn(Return node) {
3448 if (identical(node.getBeginToken().stringValue, 'native')) { 3525 if (identical(node.getBeginToken().stringValue, 'native')) {
3449 native.handleSsaNative(this, node.expression); 3526 native.handleSsaNative(this, node.expression);
3450 return; 3527 return;
3451 } 3528 }
3452 if (node.isRedirectingFactoryBody) { 3529 assert(invariant(node, !node.isRedirectingFactoryBody));
3453 compiler.internalError("Unimplemented: Redirecting factory constructor",
3454 node: node);
3455 }
3456 HInstruction value; 3530 HInstruction value;
3457 if (node.expression == null) { 3531 if (node.expression == null) {
3458 value = graph.addConstantNull(constantSystem); 3532 value = graph.addConstantNull(constantSystem);
3459 } else { 3533 } else {
3460 visit(node.expression); 3534 visit(node.expression);
3461 value = pop(); 3535 value = pop();
3462 if (value is HForeign) { 3536 if (value is HForeign) {
3463 // TODO(6530, 6534): remove this check. 3537 // TODO(6530, 6534): remove this check.
3464 } else { 3538 } else {
3465 value = potentiallyCheckType(value, returnType); 3539 value = potentiallyCheckType(value, returnType);
3466 } 3540 }
3467 } 3541 }
3542
3543 handleInTryStatement();
3544
3468 if (!inliningStack.isEmpty) { 3545 if (!inliningStack.isEmpty) {
3469 localsHandler.updateLocal(returnElement, value); 3546 localsHandler.updateLocal(returnElement, value);
3470 } else { 3547 } else {
3471 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); 3548 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit);
3472 } 3549 }
3473 } 3550 }
3474 3551
3475 visitThrow(Throw node) { 3552 visitThrow(Throw node) {
3476 if (node.expression == null) { 3553 if (node.expression == null) {
3477 HInstruction exception = rethrowableException; 3554 HInstruction exception = rethrowableException;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3548 visitEmptyStatement(EmptyStatement node) { 3625 visitEmptyStatement(EmptyStatement node) {
3549 // Do nothing, empty statement. 3626 // Do nothing, empty statement.
3550 } 3627 }
3551 3628
3552 visitModifiers(Modifiers node) { 3629 visitModifiers(Modifiers node) {
3553 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); 3630 compiler.unimplemented('SsaBuilder.visitModifiers', node: node);
3554 } 3631 }
3555 3632
3556 visitBreakStatement(BreakStatement node) { 3633 visitBreakStatement(BreakStatement node) {
3557 assert(!isAborted()); 3634 assert(!isAborted());
3635 handleInTryStatement();
3558 TargetElement target = elements[node]; 3636 TargetElement target = elements[node];
3559 assert(target != null); 3637 assert(target != null);
3560 JumpHandler handler = jumpTargets[target]; 3638 JumpHandler handler = jumpTargets[target];
3561 assert(handler != null); 3639 assert(handler != null);
3562 if (node.target == null) { 3640 if (node.target == null) {
3563 handler.generateBreak(); 3641 handler.generateBreak();
3564 } else { 3642 } else {
3565 LabelElement label = elements[node.target]; 3643 LabelElement label = elements[node.target];
3566 handler.generateBreak(label); 3644 handler.generateBreak(label);
3567 } 3645 }
3568 } 3646 }
3569 3647
3570 visitContinueStatement(ContinueStatement node) { 3648 visitContinueStatement(ContinueStatement node) {
3649 handleInTryStatement();
3571 TargetElement target = elements[node]; 3650 TargetElement target = elements[node];
3572 assert(target != null); 3651 assert(target != null);
3573 JumpHandler handler = jumpTargets[target]; 3652 JumpHandler handler = jumpTargets[target];
3574 assert(handler != null); 3653 assert(handler != null);
3575 if (node.target == null) { 3654 if (node.target == null) {
3576 handler.generateContinue(); 3655 handler.generateContinue();
3577 } else { 3656 } else {
3578 LabelElement label = elements[node.target]; 3657 LabelElement label = elements[node.target];
3579 assert(label != null); 3658 assert(label != null);
3580 handler.generateContinue(label); 3659 handler.generateContinue(label);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
3671 // a break or continue for a different target. In that case, this 3750 // a break or continue for a different target. In that case, this
3672 // label is also always unused. 3751 // label is also always unused.
3673 visit(body); 3752 visit(body);
3674 return; 3753 return;
3675 } 3754 }
3676 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); 3755 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler);
3677 assert(targetElement.isBreakTarget); 3756 assert(targetElement.isBreakTarget);
3678 JumpHandler handler = new JumpHandler(this, targetElement); 3757 JumpHandler handler = new JumpHandler(this, targetElement);
3679 // Introduce a new basic block. 3758 // Introduce a new basic block.
3680 HBasicBlock entryBlock = openNewBlock(); 3759 HBasicBlock entryBlock = openNewBlock();
3681 hackAroundPossiblyAbortingBody(node, () { visit(body); }); 3760 visit(body);
3682 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); 3761 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock);
3683 3762
3684 HBasicBlock joinBlock = graph.addNewBlock(); 3763 HBasicBlock joinBlock = graph.addNewBlock();
3685 List<LocalsHandler> breakLocals = <LocalsHandler>[]; 3764 List<LocalsHandler> breakLocals = <LocalsHandler>[];
3686 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { 3765 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
3687 breakInstruction.block.addSuccessor(joinBlock); 3766 breakInstruction.block.addSuccessor(joinBlock);
3688 breakLocals.add(locals); 3767 breakLocals.add(locals);
3689 }); 3768 });
3690 bool hasBreak = breakLocals.length > 0; 3769 bool hasBreak = breakLocals.length > 0;
3691 if (!isAborted()) { 3770 if (!isAborted()) {
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
4100 // Save the current locals. The catch block and the finally block 4179 // Save the current locals. The catch block and the finally block
4101 // must not reuse the existing locals handler. None of the variables 4180 // must not reuse the existing locals handler. None of the variables
4102 // that have been defined in the body-block will be used, but for 4181 // that have been defined in the body-block will be used, but for
4103 // loops we will add (unnecessary) phis that will reference the body 4182 // loops we will add (unnecessary) phis that will reference the body
4104 // variables. This makes it look as if the variables were used 4183 // variables. This makes it look as if the variables were used
4105 // in a non-dominated block. 4184 // in a non-dominated block.
4106 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 4185 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
4107 HBasicBlock enterBlock = openNewBlock(); 4186 HBasicBlock enterBlock = openNewBlock();
4108 HTry tryInstruction = new HTry(); 4187 HTry tryInstruction = new HTry();
4109 close(tryInstruction); 4188 close(tryInstruction);
4189 bool oldInTryStatement = inTryStatement;
4190 inTryStatement = true;
4110 4191
4111 HBasicBlock startTryBlock; 4192 HBasicBlock startTryBlock;
4112 HBasicBlock endTryBlock; 4193 HBasicBlock endTryBlock;
4113 HBasicBlock startCatchBlock; 4194 HBasicBlock startCatchBlock;
4114 HBasicBlock endCatchBlock; 4195 HBasicBlock endCatchBlock;
4115 HBasicBlock startFinallyBlock; 4196 HBasicBlock startFinallyBlock;
4116 HBasicBlock endFinallyBlock; 4197 HBasicBlock endFinallyBlock;
4117 4198
4118 startTryBlock = graph.addNewBlock(); 4199 startTryBlock = graph.addNewBlock();
4119 open(startTryBlock); 4200 open(startTryBlock);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
4214 open(startFinallyBlock); 4295 open(startFinallyBlock);
4215 visit(node.finallyBlock); 4296 visit(node.finallyBlock);
4216 if (!isAborted()) endFinallyBlock = close(new HGoto()); 4297 if (!isAborted()) endFinallyBlock = close(new HGoto());
4217 tryInstruction.finallyBlock = startFinallyBlock; 4298 tryInstruction.finallyBlock = startFinallyBlock;
4218 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock); 4299 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock);
4219 } 4300 }
4220 4301
4221 HBasicBlock exitBlock = graph.addNewBlock(); 4302 HBasicBlock exitBlock = graph.addNewBlock();
4222 4303
4223 addOptionalSuccessor(b1, b2) { if (b2 != null) b1.addSuccessor(b2); } 4304 addOptionalSuccessor(b1, b2) { if (b2 != null) b1.addSuccessor(b2); }
4305 addExitTrySuccessor(successor) {
4306 if (successor == null) return;
4307 // Iterate over all blocks created inside this try/catch, and
4308 // attach successor information to blocks that end with
4309 // [HExitTry].
4310 for (int i = startTryBlock.id; i < successor.id; i++) {
4311 HBasicBlock block = graph.blocks[i];
4312 var last = block.last;
4313 if (last is HExitTry) {
4314 block.addSuccessor(successor);
4315 } else if (last is HTry) {
4316 // Skip all blocks inside this nested try/catch.
4317 i = last.joinBlock.id;
4318 }
4319 }
4320 }
4224 4321
4225 // Setup all successors. The entry block that contains the [HTry] 4322 // Setup all successors. The entry block that contains the [HTry]
4226 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit 4323 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit
4227 // blocks as successors. 4324 // blocks as successors.
4228 enterBlock.addSuccessor(startTryBlock); 4325 enterBlock.addSuccessor(startTryBlock);
4229 addOptionalSuccessor(enterBlock, startCatchBlock); 4326 addOptionalSuccessor(enterBlock, startCatchBlock);
4230 addOptionalSuccessor(enterBlock, startFinallyBlock); 4327 addOptionalSuccessor(enterBlock, startFinallyBlock);
4231 enterBlock.addSuccessor(exitBlock); 4328 enterBlock.addSuccessor(exitBlock);
4232 4329
4233 // The body has either the catch or the finally block as successor. 4330 // The body has either the catch or the finally block as successor.
4234 if (endTryBlock != null) { 4331 if (endTryBlock != null) {
4235 assert(startCatchBlock != null || startFinallyBlock != null); 4332 assert(startCatchBlock != null || startFinallyBlock != null);
4236 endTryBlock.addSuccessor( 4333 endTryBlock.addSuccessor(
4237 startCatchBlock != null ? startCatchBlock : startFinallyBlock); 4334 startCatchBlock != null ? startCatchBlock : startFinallyBlock);
4238 } 4335 }
4239 4336
4240 // The catch block has either the finally or the exit block as 4337 // The catch block has either the finally or the exit block as
4241 // successor. 4338 // successor.
4242 if (endCatchBlock != null) { 4339 if (endCatchBlock != null) {
4243 endCatchBlock.addSuccessor( 4340 endCatchBlock.addSuccessor(
4244 startFinallyBlock != null ? startFinallyBlock : exitBlock); 4341 startFinallyBlock != null ? startFinallyBlock : exitBlock);
4245 } 4342 }
4246 4343
4247 // The finally block has the exit block as successor. 4344 // The finally block has the exit block as successor.
4248 if (endFinallyBlock != null) { 4345 if (endFinallyBlock != null) {
4249 endFinallyBlock.addSuccessor(exitBlock); 4346 endFinallyBlock.addSuccessor(exitBlock);
4250 } 4347 }
4251 4348
4349 // If a block inside try/catch aborts (eg with a return statement),
4350 // we explicitely mark this block a predecessor of the catch
4351 // block and the finally block.
4352 addExitTrySuccessor(startCatchBlock);
4353 addExitTrySuccessor(startFinallyBlock);
4354
4252 // Use the locals handler not altered by the catch and finally 4355 // Use the locals handler not altered by the catch and finally
4253 // blocks. 4356 // blocks.
4254 localsHandler = savedLocals; 4357 localsHandler = savedLocals;
4255 open(exitBlock); 4358 open(exitBlock);
4256 enterBlock.setBlockFlow( 4359 enterBlock.setBlockFlow(
4257 new HTryBlockInformation( 4360 new HTryBlockInformation(
4258 wrapStatementGraph(bodyGraph), 4361 wrapStatementGraph(bodyGraph),
4259 exception, 4362 exception,
4260 wrapStatementGraph(catchGraph), 4363 wrapStatementGraph(catchGraph),
4261 wrapStatementGraph(finallyGraph)), 4364 wrapStatementGraph(finallyGraph)),
4262 exitBlock); 4365 exitBlock);
4366 inTryStatement = oldInTryStatement;
4263 } 4367 }
4264 4368
4265 visitScriptTag(ScriptTag node) { 4369 visitScriptTag(ScriptTag node) {
4266 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node); 4370 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node);
4267 } 4371 }
4268 4372
4269 visitCatchBlock(CatchBlock node) { 4373 visitCatchBlock(CatchBlock node) {
4270 visit(node.block); 4374 visit(node.block);
4271 } 4375 }
4272 4376
(...skipping 10 matching lines...) Expand all
4283 ClassElement element = concreteType.getUniqueType(); 4387 ClassElement element = concreteType.getUniqueType();
4284 if (element == null) return HType.UNKNOWN; 4388 if (element == null) return HType.UNKNOWN;
4285 if (element == builder.compiler.boolClass) return HType.BOOLEAN; 4389 if (element == builder.compiler.boolClass) return HType.BOOLEAN;
4286 if (element == builder.compiler.doubleClass) return HType.DOUBLE; 4390 if (element == builder.compiler.doubleClass) return HType.DOUBLE;
4287 if (element == builder.compiler.intClass) return HType.INTEGER; 4391 if (element == builder.compiler.intClass) return HType.INTEGER;
4288 if (element == builder.compiler.listClass) return HType.READABLE_ARRAY; 4392 if (element == builder.compiler.listClass) return HType.READABLE_ARRAY;
4289 if (element == builder.compiler.nullClass) return HType.NULL; 4393 if (element == builder.compiler.nullClass) return HType.NULL;
4290 if (element == builder.compiler.stringClass) return HType.STRING; 4394 if (element == builder.compiler.stringClass) return HType.STRING;
4291 return HType.UNKNOWN; 4395 return HType.UNKNOWN;
4292 } 4396 }
4293
4294 /** HACK HACK HACK */
4295 void hackAroundPossiblyAbortingBody(Node statement, void body()) {
4296 visitCondition() {
4297 stack.add(graph.addConstantBool(true, constantSystem));
4298 }
4299 buildBody() {
4300 // TODO(lrn): Make sure to take continue into account.
4301 body();
4302 }
4303 handleIf(statement, visitCondition, buildBody, null);
4304 }
4305 } 4397 }
4306 4398
4307 /** 4399 /**
4308 * Visitor that handles generation of string literals (LiteralString, 4400 * Visitor that handles generation of string literals (LiteralString,
4309 * StringInterpolation), and otherwise delegates to the given visitor for 4401 * StringInterpolation), and otherwise delegates to the given visitor for
4310 * non-literal subexpressions. 4402 * non-literal subexpressions.
4311 * TODO(lrn): Consider whether to handle compile time constant int/boolean 4403 * TODO(lrn): Consider whether to handle compile time constant int/boolean
4312 * expressions as well. 4404 * expressions as well.
4313 */ 4405 */
4314 class StringBuilderVisitor extends Visitor { 4406 class StringBuilderVisitor extends Visitor {
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
4679 new HSubGraphBlockInformation(elseBranch.graph)); 4771 new HSubGraphBlockInformation(elseBranch.graph));
4680 4772
4681 HBasicBlock conditionStartBlock = conditionBranch.block; 4773 HBasicBlock conditionStartBlock = conditionBranch.block;
4682 conditionStartBlock.setBlockFlow(info, joinBlock); 4774 conditionStartBlock.setBlockFlow(info, joinBlock);
4683 SubGraph conditionGraph = conditionBranch.graph; 4775 SubGraph conditionGraph = conditionBranch.graph;
4684 HIf branch = conditionGraph.end.last; 4776 HIf branch = conditionGraph.end.last;
4685 assert(branch is HIf); 4777 assert(branch is HIf);
4686 branch.blockInformation = conditionStartBlock.blockFlow; 4778 branch.blockInformation = conditionStartBlock.blockFlow;
4687 } 4779 }
4688 } 4780 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698