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 |