| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class Interceptors { | 7 class Interceptors { |
| 8 Compiler compiler; | 8 Compiler compiler; |
| 9 Interceptors(Compiler this.compiler); | 9 Interceptors(Compiler this.compiler); |
| 10 | 10 |
| (...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 abstract class JumpHandler { | 764 abstract class JumpHandler { |
| 765 factory JumpHandler(SsaBuilder builder, TargetElement target) { | 765 factory JumpHandler(SsaBuilder builder, TargetElement target) { |
| 766 return new TargetJumpHandler(builder, target); | 766 return new TargetJumpHandler(builder, target); |
| 767 } | 767 } |
| 768 void generateBreak([LabelElement label]); | 768 void generateBreak([LabelElement label]); |
| 769 void generateContinue([LabelElement label]); | 769 void generateContinue([LabelElement label]); |
| 770 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); | 770 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); |
| 771 void forEachContinue(void action(HContinue instruction, | 771 void forEachContinue(void action(HContinue instruction, |
| 772 LocalsHandler locals)); | 772 LocalsHandler locals)); |
| 773 bool hasAnyContinue(); | 773 bool hasAnyContinue(); |
| 774 bool hasAnyBreak(); |
| 774 void close(); | 775 void close(); |
| 775 final TargetElement target; | 776 final TargetElement target; |
| 776 List<LabelElement> labels(); | 777 List<LabelElement> labels(); |
| 777 } | 778 } |
| 778 | 779 |
| 779 // Insert break handler used to avoid null checks when a target isn't | 780 // Insert break handler used to avoid null checks when a target isn't |
| 780 // used as the target of a break, and therefore doesn't need a break | 781 // used as the target of a break, and therefore doesn't need a break |
| 781 // handler associated with it. | 782 // handler associated with it. |
| 782 class NullJumpHandler implements JumpHandler { | 783 class NullJumpHandler implements JumpHandler { |
| 783 final Compiler compiler; | 784 final Compiler compiler; |
| 784 | 785 |
| 785 NullJumpHandler(this.compiler); | 786 NullJumpHandler(this.compiler); |
| 786 | 787 |
| 787 void generateBreak([LabelElement label]) { | 788 void generateBreak([LabelElement label]) { |
| 788 compiler.internalError('generateBreak should not be called'); | 789 compiler.internalError('generateBreak should not be called'); |
| 789 } | 790 } |
| 790 | 791 |
| 791 void generateContinue([LabelElement label]) { | 792 void generateContinue([LabelElement label]) { |
| 792 compiler.internalError('generateContinue should not be called'); | 793 compiler.internalError('generateContinue should not be called'); |
| 793 } | 794 } |
| 794 | 795 |
| 795 void forEachBreak(Function ignored) { } | 796 void forEachBreak(Function ignored) { } |
| 796 void forEachContinue(Function ignored) { } | 797 void forEachContinue(Function ignored) { } |
| 797 void close() { } | 798 void close() { } |
| 798 bool hasAnyContinue() => false; | 799 bool hasAnyContinue() => false; |
| 800 bool hasAnyBreak() => false; |
| 799 | 801 |
| 800 List<LabelElement> labels() => const <LabelElement>[]; | 802 List<LabelElement> labels() => const <LabelElement>[]; |
| 801 TargetElement get target => null; | 803 TargetElement get target => null; |
| 802 } | 804 } |
| 803 | 805 |
| 804 // Records breaks until a target block is available. | 806 // Records breaks until a target block is available. |
| 805 // Breaks are always forward jumps. | 807 // Breaks are always forward jumps. |
| 806 // Continues in loops are implemented as breaks of the body. | 808 // Continues in loops are implemented as breaks of the body. |
| 807 // Continues in switches is currently not handled. | 809 // Continues in switches is currently not handled. |
| 808 class TargetJumpHandler implements JumpHandler { | 810 class TargetJumpHandler implements JumpHandler { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 } | 855 } |
| 854 } | 856 } |
| 855 | 857 |
| 856 bool hasAnyContinue() { | 858 bool hasAnyContinue() { |
| 857 for (JumpHandlerEntry entry in jumps) { | 859 for (JumpHandlerEntry entry in jumps) { |
| 858 if (entry.isContinue()) return true; | 860 if (entry.isContinue()) return true; |
| 859 } | 861 } |
| 860 return false; | 862 return false; |
| 861 } | 863 } |
| 862 | 864 |
| 865 bool hasAnyBreak() { |
| 866 for (JumpHandlerEntry entry in jumps) { |
| 867 if (entry.isBreak()) return true; |
| 868 } |
| 869 return false; |
| 870 } |
| 871 |
| 863 void close() { | 872 void close() { |
| 864 // The mapping from TargetElement to JumpHandler is no longer needed. | 873 // The mapping from TargetElement to JumpHandler is no longer needed. |
| 865 builder.jumpTargets.remove(target); | 874 builder.jumpTargets.remove(target); |
| 866 } | 875 } |
| 867 | 876 |
| 868 List<LabelElement> labels() { | 877 List<LabelElement> labels() { |
| 869 List<LabelElement> result = null; | 878 List<LabelElement> result = null; |
| 870 for (LabelElement element in target.labels) { | 879 for (LabelElement element in target.labels) { |
| 871 if (result == null) result = <LabelElement>[]; | 880 if (result == null) result = <LabelElement>[]; |
| 872 result.add(element); | 881 result.add(element); |
| (...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1721 /** | 1730 /** |
| 1722 * Ends the loop: | 1731 * Ends the loop: |
| 1723 * - creates a new block and adds it as successor to the [branchBlock]. | 1732 * - creates a new block and adds it as successor to the [branchBlock]. |
| 1724 * - opens the new block (setting as [current]). | 1733 * - opens the new block (setting as [current]). |
| 1725 * - notifies the locals handler that we're exiting a loop. | 1734 * - notifies the locals handler that we're exiting a loop. |
| 1726 */ | 1735 */ |
| 1727 void endLoop(HBasicBlock loopEntry, | 1736 void endLoop(HBasicBlock loopEntry, |
| 1728 HBasicBlock branchBlock, | 1737 HBasicBlock branchBlock, |
| 1729 JumpHandler jumpHandler, | 1738 JumpHandler jumpHandler, |
| 1730 LocalsHandler savedLocals) { | 1739 LocalsHandler savedLocals) { |
| 1740 if (branchBlock == null && !jumpHandler.hasAnyBreak()) return; |
| 1741 |
| 1731 HBasicBlock loopExitBlock = addNewBlock(); | 1742 HBasicBlock loopExitBlock = addNewBlock(); |
| 1732 assert(branchBlock.successors.length == 1); | 1743 assert(branchBlock == null || branchBlock.successors.length == 1); |
| 1733 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 1744 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
| 1734 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 1745 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
| 1735 breakInstruction.block.addSuccessor(loopExitBlock); | 1746 breakInstruction.block.addSuccessor(loopExitBlock); |
| 1736 breakLocals.add(locals); | 1747 breakLocals.add(locals); |
| 1737 }); | 1748 }); |
| 1738 branchBlock.addSuccessor(loopExitBlock); | 1749 if (branchBlock != null) { |
| 1750 branchBlock.addSuccessor(loopExitBlock); |
| 1751 } |
| 1739 open(loopExitBlock); | 1752 open(loopExitBlock); |
| 1740 localsHandler.endLoop(loopEntry); | 1753 localsHandler.endLoop(loopEntry); |
| 1741 if (!breakLocals.isEmpty) { | 1754 if (!breakLocals.isEmpty) { |
| 1742 breakLocals.add(savedLocals); | 1755 breakLocals.add(savedLocals); |
| 1743 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock); | 1756 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock); |
| 1744 } else { | 1757 } else { |
| 1745 localsHandler = savedLocals; | 1758 localsHandler = savedLocals; |
| 1746 } | 1759 } |
| 1747 } | 1760 } |
| 1748 | 1761 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1946 // Add extra block to hang labels on. | 1959 // Add extra block to hang labels on. |
| 1947 // It doesn't currently work if they are on the same block as the | 1960 // It doesn't currently work if they are on the same block as the |
| 1948 // HLoopInfo. The handling of HLabeledBlockInformation will visit a | 1961 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
| 1949 // SubGraph that starts at the same block again, so the HLoopInfo is | 1962 // SubGraph that starts at the same block again, so the HLoopInfo is |
| 1950 // either handled twice, or it's handled after the labeled block info, | 1963 // either handled twice, or it's handled after the labeled block info, |
| 1951 // both of which generate the wrong code. | 1964 // both of which generate the wrong code. |
| 1952 // Using a separate block is just a simple workaround. | 1965 // Using a separate block is just a simple workaround. |
| 1953 bodyEntryBlock = openNewBlock(); | 1966 bodyEntryBlock = openNewBlock(); |
| 1954 } | 1967 } |
| 1955 localsHandler.enterLoopBody(node); | 1968 localsHandler.enterLoopBody(node); |
| 1956 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); | 1969 visit(node.body); |
| 1957 | 1970 |
| 1958 // If there are no continues we could avoid the creation of the condition | 1971 // If there are no continues we could avoid the creation of the condition |
| 1959 // block. This could also lead to a block having multiple entries and exits. | 1972 // block. This could also lead to a block having multiple entries and exits. |
| 1960 HBasicBlock bodyExitBlock = close(new HGoto()); | 1973 HBasicBlock bodyExitBlock; |
| 1961 HBasicBlock conditionBlock = addNewBlock(); | 1974 bool isAbortingBody = false; |
| 1975 if (current != null) { |
| 1976 bodyExitBlock = close(new HGoto()); |
| 1977 } else { |
| 1978 isAbortingBody = true; |
| 1979 bodyExitBlock = lastOpenedBlock; |
| 1980 } |
| 1962 | 1981 |
| 1963 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1982 SubExpression conditionExpression; |
| 1964 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 1983 HBasicBlock conditionEndBlock; |
| 1965 instruction.block.addSuccessor(conditionBlock); | 1984 if (!isAbortingBody || hasContinues) { |
| 1966 continueLocals.add(locals); | 1985 HBasicBlock conditionBlock = addNewBlock(); |
| 1967 }); | 1986 |
| 1968 bodyExitBlock.addSuccessor(conditionBlock); | 1987 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
| 1969 if (!continueLocals.isEmpty) { | 1988 jumpHandler.forEachContinue((HContinue instruction, |
| 1970 continueLocals.add(localsHandler); | 1989 LocalsHandler locals) { |
| 1971 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); | 1990 instruction.block.addSuccessor(conditionBlock); |
| 1972 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 1991 continueLocals.add(locals); |
| 1973 List<LabelElement> labels = jumpHandler.labels(); | 1992 }); |
| 1974 HSubGraphBlockInformation bodyInfo = | 1993 |
| 1975 new HSubGraphBlockInformation(bodyGraph); | 1994 if (!isAbortingBody) { |
| 1976 HLabeledBlockInformation info; | 1995 bodyExitBlock.addSuccessor(conditionBlock); |
| 1977 if (!labels.isEmpty) { | |
| 1978 info = new HLabeledBlockInformation(bodyInfo, labels, isContinue: true); | |
| 1979 } else { | |
| 1980 info = new HLabeledBlockInformation.implicit(bodyInfo, target, | |
| 1981 isContinue: true); | |
| 1982 } | 1996 } |
| 1983 bodyEntryBlock.setBlockFlow(info, conditionBlock); | 1997 |
| 1998 if (!continueLocals.isEmpty) { |
| 1999 if (!isAbortingBody) continueLocals.add(localsHandler); |
| 2000 localsHandler = |
| 2001 savedLocals.mergeMultiple(continueLocals, conditionBlock); |
| 2002 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 2003 List<LabelElement> labels = jumpHandler.labels(); |
| 2004 HSubGraphBlockInformation bodyInfo = |
| 2005 new HSubGraphBlockInformation(bodyGraph); |
| 2006 HLabeledBlockInformation info; |
| 2007 if (!labels.isEmpty) { |
| 2008 info = new HLabeledBlockInformation(bodyInfo, labels, |
| 2009 isContinue: true); |
| 2010 } else { |
| 2011 info = new HLabeledBlockInformation.implicit(bodyInfo, target, |
| 2012 isContinue: true); |
| 2013 } |
| 2014 bodyEntryBlock.setBlockFlow(info, conditionBlock); |
| 2015 } |
| 2016 open(conditionBlock); |
| 2017 |
| 2018 visit(node.condition); |
| 2019 assert(!isAborted()); |
| 2020 HInstruction conditionInstruction = popBoolified(); |
| 2021 conditionEndBlock = close( |
| 2022 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); |
| 2023 |
| 2024 conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge. |
| 2025 conditionExpression = |
| 2026 new SubExpression(conditionBlock, conditionEndBlock); |
| 1984 } | 2027 } |
| 1985 open(conditionBlock); | |
| 1986 | 2028 |
| 1987 visit(node.condition); | |
| 1988 assert(!isAborted()); | |
| 1989 HInstruction conditionInstruction = popBoolified(); | |
| 1990 HBasicBlock conditionEndBlock = | |
| 1991 close(new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); | |
| 1992 | |
| 1993 conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge. | |
| 1994 loopEntryBlock.postProcessLoopHeader(); | 2029 loopEntryBlock.postProcessLoopHeader(); |
| 1995 | 2030 |
| 1996 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); | 2031 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); |
| 1997 jumpHandler.close(); | 2032 jumpHandler.close(); |
| 1998 | 2033 |
| 1999 SubExpression conditionExpression = | |
| 2000 new SubExpression(conditionBlock, conditionEndBlock); | |
| 2001 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 2034 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 2002 | 2035 |
| 2003 HLoopBlockInformation loopBlockInfo = | 2036 HLoopBlockInformation loopBlockInfo = |
| 2004 new HLoopBlockInformation( | 2037 new HLoopBlockInformation( |
| 2005 HLoopBlockInformation.DO_WHILE_LOOP, | 2038 HLoopBlockInformation.DO_WHILE_LOOP, |
| 2006 null, | 2039 null, |
| 2007 wrapExpressionGraph(conditionExpression), | 2040 wrapExpressionGraph(conditionExpression), |
| 2008 wrapStatementGraph(bodyGraph), | 2041 wrapStatementGraph(bodyGraph), |
| 2009 null, | 2042 null, |
| 2010 loopEntryBlock.loopInformation.target, | 2043 loopEntryBlock.loopInformation.target, |
| (...skipping 2731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4742 new HSubGraphBlockInformation(elseBranch.graph)); | 4775 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4743 | 4776 |
| 4744 HBasicBlock conditionStartBlock = conditionBranch.block; | 4777 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4745 conditionStartBlock.setBlockFlow(info, joinBlock); | 4778 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4746 SubGraph conditionGraph = conditionBranch.graph; | 4779 SubGraph conditionGraph = conditionBranch.graph; |
| 4747 HIf branch = conditionGraph.end.last; | 4780 HIf branch = conditionGraph.end.last; |
| 4748 assert(branch is HIf); | 4781 assert(branch is HIf); |
| 4749 branch.blockInformation = conditionStartBlock.blockFlow; | 4782 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4750 } | 4783 } |
| 4751 } | 4784 } |
| OLD | NEW |