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 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 // In all other cases a new box will be created when entering the body of | 658 // In all other cases a new box will be created when entering the body of |
659 // the next iteration. | 659 // the next iteration. |
660 ClosureScope scopeData = closureData.capturingScopes[node]; | 660 ClosureScope scopeData = closureData.capturingScopes[node]; |
661 if (scopeData == null) return; | 661 if (scopeData == null) return; |
662 if (scopeData.hasBoxedLoopVariables()) { | 662 if (scopeData.hasBoxedLoopVariables()) { |
663 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables); | 663 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables); |
664 } | 664 } |
665 } | 665 } |
666 | 666 |
667 void endLoop(HBasicBlock loopEntry) { | 667 void endLoop(HBasicBlock loopEntry) { |
668 // If the loop has an aborting body, we don't update the loop | |
669 // phis. | |
670 if (loopEntry.predecessors.length == 1) return; | |
668 loopEntry.forEachPhi((HPhi phi) { | 671 loopEntry.forEachPhi((HPhi phi) { |
669 Element element = phi.sourceElement; | 672 Element element = phi.sourceElement; |
670 HInstruction postLoopDefinition = directLocals[element]; | 673 HInstruction postLoopDefinition = directLocals[element]; |
671 phi.addInput(postLoopDefinition); | 674 phi.addInput(postLoopDefinition); |
672 }); | 675 }); |
673 } | 676 } |
674 | 677 |
675 /** | 678 /** |
676 * Merge [otherLocals] into this locals handler, creating phi-nodes when | 679 * Merge [otherLocals] into this locals handler, creating phi-nodes when |
677 * there is a conflict. | 680 * there is a conflict. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
760 | 763 |
761 abstract class JumpHandler { | 764 abstract class JumpHandler { |
762 factory JumpHandler(SsaBuilder builder, TargetElement target) { | 765 factory JumpHandler(SsaBuilder builder, TargetElement target) { |
763 return new TargetJumpHandler(builder, target); | 766 return new TargetJumpHandler(builder, target); |
764 } | 767 } |
765 void generateBreak([LabelElement label]); | 768 void generateBreak([LabelElement label]); |
766 void generateContinue([LabelElement label]); | 769 void generateContinue([LabelElement label]); |
767 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); | 770 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); |
768 void forEachContinue(void action(HContinue instruction, | 771 void forEachContinue(void action(HContinue instruction, |
769 LocalsHandler locals)); | 772 LocalsHandler locals)); |
773 bool hasAnyContinue(); | |
770 void close(); | 774 void close(); |
771 final TargetElement target; | 775 final TargetElement target; |
772 List<LabelElement> labels(); | 776 List<LabelElement> labels(); |
773 } | 777 } |
774 | 778 |
775 // Insert break handler used to avoid null checks when a target isn't | 779 // 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 | 780 // used as the target of a break, and therefore doesn't need a break |
777 // handler associated with it. | 781 // handler associated with it. |
778 class NullJumpHandler implements JumpHandler { | 782 class NullJumpHandler implements JumpHandler { |
779 final Compiler compiler; | 783 final Compiler compiler; |
780 | 784 |
781 NullJumpHandler(this.compiler); | 785 NullJumpHandler(this.compiler); |
782 | 786 |
783 void generateBreak([LabelElement label]) { | 787 void generateBreak([LabelElement label]) { |
784 compiler.internalError('generateBreak should not be called'); | 788 compiler.internalError('generateBreak should not be called'); |
785 } | 789 } |
786 | 790 |
787 void generateContinue([LabelElement label]) { | 791 void generateContinue([LabelElement label]) { |
788 compiler.internalError('generateContinue should not be called'); | 792 compiler.internalError('generateContinue should not be called'); |
789 } | 793 } |
790 | 794 |
791 void forEachBreak(Function ignored) { } | 795 void forEachBreak(Function ignored) { } |
792 void forEachContinue(Function ignored) { } | 796 void forEachContinue(Function ignored) { } |
793 void close() { } | 797 void close() { } |
798 bool hasAnyContinue() => 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 Loading... | |
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 | |
851 void close() { | 863 void close() { |
852 // The mapping from TargetElement to JumpHandler is no longer needed. | 864 // The mapping from TargetElement to JumpHandler is no longer needed. |
853 builder.jumpTargets.remove(target); | 865 builder.jumpTargets.remove(target); |
854 } | 866 } |
855 | 867 |
856 List<LabelElement> labels() { | 868 List<LabelElement> labels() { |
857 List<LabelElement> result = null; | 869 List<LabelElement> result = null; |
858 for (LabelElement element in target.labels) { | 870 for (LabelElement element in target.labels) { |
859 if (result == null) result = <LabelElement>[]; | 871 if (result == null) result = <LabelElement>[]; |
860 result.add(element); | 872 result.add(element); |
(...skipping 925 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1786 new SubExpression(conditionBlock, conditionExitBlock); | 1798 new SubExpression(conditionBlock, conditionExitBlock); |
1787 | 1799 |
1788 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1800 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1789 | 1801 |
1790 // The body. | 1802 // The body. |
1791 HBasicBlock beginBodyBlock = addNewBlock(); | 1803 HBasicBlock beginBodyBlock = addNewBlock(); |
1792 conditionExitBlock.addSuccessor(beginBodyBlock); | 1804 conditionExitBlock.addSuccessor(beginBodyBlock); |
1793 open(beginBodyBlock); | 1805 open(beginBodyBlock); |
1794 | 1806 |
1795 localsHandler.enterLoopBody(loop); | 1807 localsHandler.enterLoopBody(loop); |
1796 hackAroundPossiblyAbortingBody(loop, body); | 1808 body(); |
1797 | 1809 |
1798 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); | 1810 SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock); |
1799 HBasicBlock bodyBlock = close(new HGoto()); | 1811 HBasicBlock bodyBlock = current; |
1812 if (current != null) close(new HGoto()); | |
1800 | 1813 |
1801 // Update. | 1814 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 | 1815 |
1807 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1816 // Check that the loop has at least one back-edge. |
1808 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 1817 if (jumpHandler.hasAnyContinue() || bodyBlock != null) { |
1809 instruction.block.addSuccessor(updateBlock); | 1818 // Update. |
1810 continueLocals.add(locals); | 1819 // We create an update block, even when we are in a while loop. There the |
1811 }); | 1820 // update block is the jump-target for continue statements. We could avoid |
floitsch
2012/11/05 17:36:09
It seems trivial to avoid the creation of the bloc
ngeoffray
2012/11/06 08:55:27
Will do in another CL.
| |
1812 bodyBlock.addSuccessor(updateBlock); | 1821 // the creation if there is no continue, but for now we always create it. |
1813 continueLocals.add(localsHandler); | 1822 HBasicBlock updateBlock = addNewBlock(); |
1814 | 1823 |
1815 open(updateBlock); | 1824 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
1825 jumpHandler.forEachContinue((HContinue instruction, | |
1826 LocalsHandler locals) { | |
1827 instruction.block.addSuccessor(updateBlock); | |
1828 continueLocals.add(locals); | |
1829 }); | |
1816 | 1830 |
1817 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); | |
1818 | 1831 |
1819 HLabeledBlockInformation labelInfo; | 1832 if (bodyBlock != null) { |
1820 List<LabelElement> labels = jumpHandler.labels(); | 1833 continueLocals.add(localsHandler); |
1821 TargetElement target = elements[loop]; | 1834 bodyBlock.addSuccessor(updateBlock); |
1822 if (!labels.isEmpty) { | 1835 } |
1823 beginBodyBlock.setBlockFlow( | 1836 |
1824 new HLabeledBlockInformation( | 1837 open(updateBlock); |
1825 new HSubGraphBlockInformation(bodyGraph), | 1838 localsHandler = |
1826 jumpHandler.labels(), | 1839 continueLocals[0].mergeMultiple(continueLocals, updateBlock); |
1827 isContinue: true), | 1840 |
1828 updateBlock); | 1841 HLabeledBlockInformation labelInfo; |
1829 } else if (target != null && target.isContinueTarget) { | 1842 List<LabelElement> labels = jumpHandler.labels(); |
1830 beginBodyBlock.setBlockFlow( | 1843 TargetElement target = elements[loop]; |
1831 new HLabeledBlockInformation.implicit( | 1844 if (!labels.isEmpty) { |
1832 new HSubGraphBlockInformation(bodyGraph), | 1845 beginBodyBlock.setBlockFlow( |
1833 target, | 1846 new HLabeledBlockInformation( |
1834 isContinue: true), | 1847 new HSubGraphBlockInformation(bodyGraph), |
1835 updateBlock); | 1848 jumpHandler.labels(), |
1849 isContinue: true), | |
1850 updateBlock); | |
1851 } else if (target != null && target.isContinueTarget) { | |
1852 beginBodyBlock.setBlockFlow( | |
1853 new HLabeledBlockInformation.implicit( | |
1854 new HSubGraphBlockInformation(bodyGraph), | |
1855 target, | |
1856 isContinue: true), | |
1857 updateBlock); | |
1858 } | |
1859 | |
1860 localsHandler.enterLoopUpdates(loop); | |
1861 | |
1862 update(); | |
1863 | |
1864 HBasicBlock updateEndBlock = close(new HGoto()); | |
1865 // The back-edge completing the cycle. | |
1866 updateEndBlock.addSuccessor(conditionBlock); | |
1867 updateGraph = new SubExpression(updateBlock, updateEndBlock); | |
1836 } | 1868 } |
1837 | 1869 |
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(); | 1870 conditionBlock.postProcessLoopHeader(); |
1846 SubExpression updateGraph = new SubExpression(updateBlock, updateEndBlock); | |
1847 | 1871 |
1848 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); | 1872 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
1849 HLoopBlockInformation info = | 1873 HLoopBlockInformation info = |
1850 new HLoopBlockInformation( | 1874 new HLoopBlockInformation( |
1851 HLoopBlockInformation.loopType(loop), | 1875 HLoopBlockInformation.loopType(loop), |
1852 wrapExpressionGraph(initializerGraph), | 1876 wrapExpressionGraph(initializerGraph), |
1853 wrapExpressionGraph(conditionExpression), | 1877 wrapExpressionGraph(conditionExpression), |
1854 wrapStatementGraph(bodyGraph), | 1878 wrapStatementGraph(bodyGraph), |
1855 wrapExpressionGraph(updateGraph), | 1879 wrapExpressionGraph(updateGraph), |
1856 conditionBlock.loopInformation.target, | 1880 conditionBlock.loopInformation.target, |
(...skipping 2822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4679 new HSubGraphBlockInformation(elseBranch.graph)); | 4703 new HSubGraphBlockInformation(elseBranch.graph)); |
4680 | 4704 |
4681 HBasicBlock conditionStartBlock = conditionBranch.block; | 4705 HBasicBlock conditionStartBlock = conditionBranch.block; |
4682 conditionStartBlock.setBlockFlow(info, joinBlock); | 4706 conditionStartBlock.setBlockFlow(info, joinBlock); |
4683 SubGraph conditionGraph = conditionBranch.graph; | 4707 SubGraph conditionGraph = conditionBranch.graph; |
4684 HIf branch = conditionGraph.end.last; | 4708 HIf branch = conditionGraph.end.last; |
4685 assert(branch is HIf); | 4709 assert(branch is HIf); |
4686 branch.blockInformation = conditionStartBlock.blockFlow; | 4710 branch.blockInformation = conditionStartBlock.blockFlow; |
4687 } | 4711 } |
4688 } | 4712 } |
OLD | NEW |