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 /** | 7 /** |
8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
489 if (scopeData == null) return; | 489 if (scopeData == null) return; |
490 if (scopeData.hasBoxedLoopVariables()) { | 490 if (scopeData.hasBoxedLoopVariables()) { |
491 // If there are boxed loop variables then we set up the box and | 491 // If there are boxed loop variables then we set up the box and |
492 // redirections already now. This way the initializer can write its | 492 // redirections already now. This way the initializer can write its |
493 // values into the box. | 493 // values into the box. |
494 // For other loops the box will be created when entering the body. | 494 // For other loops the box will be created when entering the body. |
495 enterScope(node, null); | 495 enterScope(node, null); |
496 } | 496 } |
497 } | 497 } |
498 | 498 |
499 void beginLoopHeader(Node node, HBasicBlock loopEntry) { | 499 /** |
500 * Create phis at the loop entry for local variables (ready for the values | |
501 * from the back edge). Populate the phis with the current values. | |
502 */ | |
503 void beginLoopHeader(HBasicBlock loopEntry) { | |
500 // Create a copy because we modify the map while iterating over it. | 504 // Create a copy because we modify the map while iterating over it. |
501 Map<Element, HInstruction> saved = | 505 Map<Element, HInstruction> savedDirectLocals = |
502 new LinkedHashMap<Element, HInstruction>.from(directLocals); | 506 new LinkedHashMap<Element, HInstruction>.from(directLocals); |
503 | 507 |
504 // Create phis for all elements in the definitions environment. | 508 // Create phis for all elements in the definitions environment. |
505 saved.forEach((Element element, HInstruction instruction) { | 509 savedDirectLocals.forEach((Element element, HInstruction instruction) { |
506 if (isAccessedDirectly(element)) { | 510 if (isAccessedDirectly(element)) { |
507 // We know 'this' cannot be modified. | 511 // We know 'this' cannot be modified. |
508 if (!identical(element, closureData.thisElement)) { | 512 if (!identical(element, closureData.thisElement)) { |
509 HPhi phi = new HPhi.singleInput(element, instruction); | 513 HPhi phi = new HPhi.singleInput(element, instruction); |
510 loopEntry.addPhi(phi); | 514 loopEntry.addPhi(phi); |
511 directLocals[element] = phi; | 515 directLocals[element] = phi; |
512 } else { | 516 } else { |
513 directLocals[element] = instruction; | 517 directLocals[element] = instruction; |
514 } | 518 } |
515 } | 519 } |
(...skipping 16 matching lines...) Expand all Loading... | |
532 // updates. | 536 // updates. |
533 // In all other cases a new box will be created when entering the body of | 537 // In all other cases a new box will be created when entering the body of |
534 // the next iteration. | 538 // the next iteration. |
535 ClosureScope scopeData = closureData.capturingScopes[node]; | 539 ClosureScope scopeData = closureData.capturingScopes[node]; |
536 if (scopeData == null) return; | 540 if (scopeData == null) return; |
537 if (scopeData.hasBoxedLoopVariables()) { | 541 if (scopeData.hasBoxedLoopVariables()) { |
538 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables); | 542 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables); |
539 } | 543 } |
540 } | 544 } |
541 | 545 |
546 /** | |
547 * Goes through the phis created in beginLoopHeader entry and adds the | |
548 * input from the back edge (from the current value of directLocals) to them. | |
549 */ | |
542 void endLoop(HBasicBlock loopEntry) { | 550 void endLoop(HBasicBlock loopEntry) { |
543 // If the loop has an aborting body, we don't update the loop | 551 // If the loop has an aborting body, we don't update the loop |
544 // phis. | 552 // phis. |
545 if (loopEntry.predecessors.length == 1) return; | 553 if (loopEntry.predecessors.length == 1) return; |
546 loopEntry.forEachPhi((HPhi phi) { | 554 loopEntry.forEachPhi((HPhi phi) { |
547 Element element = phi.sourceElement; | 555 Element element = phi.sourceElement; |
548 HInstruction postLoopDefinition = directLocals[element]; | 556 HInstruction postLoopDefinition = directLocals[element]; |
549 phi.addInput(postLoopDefinition); | 557 phi.addInput(postLoopDefinition); |
550 }); | 558 }); |
551 } | 559 } |
(...skipping 27 matching lines...) Expand all Loading... | |
579 new HPhi.manyInputs(element, <HInstruction>[mine, instruction]); | 587 new HPhi.manyInputs(element, <HInstruction>[mine, instruction]); |
580 joinBlock.addPhi(phi); | 588 joinBlock.addPhi(phi); |
581 joinedLocals[element] = phi; | 589 joinedLocals[element] = phi; |
582 } | 590 } |
583 } | 591 } |
584 }); | 592 }); |
585 directLocals = joinedLocals; | 593 directLocals = joinedLocals; |
586 } | 594 } |
587 | 595 |
588 /** | 596 /** |
589 * The current localsHandler is not used for its values, only for its | 597 * When control flow merges, this method can be used to merge several |
590 * declared variables. This is a way to exclude local values from the | 598 * localsHandlers into a new one using phis. The new localsHandler is |
591 * result when they are no longer in scope. | 599 * returned. Unless it is also in the list, the current localsHandler is not |
592 * Returns the new LocalsHandler to use (may not be [this]). | 600 * used for its values, only for its declared variables. This is a way to |
601 * exclude local values from the result when they are no longer in scope. | |
593 */ | 602 */ |
594 LocalsHandler mergeMultiple(List<LocalsHandler> locals, | 603 LocalsHandler mergeMultiple(List<LocalsHandler> localsHandlers, |
595 HBasicBlock joinBlock) { | 604 HBasicBlock joinBlock) { |
596 assert(locals.length > 0); | 605 assert(localsHandlers.length > 0); |
597 if (locals.length == 1) return locals[0]; | 606 if (localsHandlers.length == 1) return localsHandlers[0]; |
598 Map<Element, HInstruction> joinedLocals = | 607 Map<Element, HInstruction> joinedLocals = |
599 new LinkedHashMap<Element,HInstruction>(); | 608 new LinkedHashMap<Element,HInstruction>(); |
600 HInstruction thisValue = null; | 609 HInstruction thisValue = null; |
601 directLocals.forEach((Element element, HInstruction instruction) { | 610 directLocals.forEach((Element element, HInstruction instruction) { |
602 if (!identical(element, closureData.thisElement)) { | 611 if (!identical(element, closureData.thisElement)) { |
603 HPhi phi = new HPhi.noInputs(element); | 612 HPhi phi = new HPhi.noInputs(element); |
604 joinedLocals[element] = phi; | 613 joinedLocals[element] = phi; |
605 joinBlock.addPhi(phi); | 614 joinBlock.addPhi(phi); |
606 } else { | 615 } else { |
607 // We know that "this" never changes, if it's there. | 616 // We know that "this" never changes, if it's there. |
608 // Save it for later. While merging, there is no phi for "this", | 617 // Save it for later. While merging, there is no phi for "this", |
609 // so we don't have to special case it in the merge loop. | 618 // so we don't have to special case it in the merge loop. |
610 thisValue = instruction; | 619 thisValue = instruction; |
611 } | 620 } |
612 }); | 621 }); |
613 for (LocalsHandler local in locals) { | 622 for (LocalsHandler handler in localsHandlers) { |
614 local.directLocals.forEach((Element element, HInstruction instruction) { | 623 handler.directLocals.forEach((Element element, HInstruction instruction) { |
615 HPhi phi = joinedLocals[element]; | 624 HPhi phi = joinedLocals[element]; |
616 if (phi != null) { | 625 if (phi != null) { |
617 phi.addInput(instruction); | 626 phi.addInput(instruction); |
618 } | 627 } |
619 }); | 628 }); |
620 } | 629 } |
621 if (thisValue != null) { | 630 if (thisValue != null) { |
622 // If there was a "this" for the scope, add it to the new locals. | 631 // If there was a "this" for the scope, add it to the new locals. |
623 joinedLocals[closureData.thisElement] = thisValue; | 632 joinedLocals[closureData.thisElement] = thisValue; |
624 } | 633 } |
(...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1729 Script script = element.getCompilationUnit().script; | 1738 Script script = element.getCompilationUnit().script; |
1730 SourceFile sourceFile = script.file; | 1739 SourceFile sourceFile = script.file; |
1731 SourceFileLocation location = new SourceFileLocation(sourceFile, token); | 1740 SourceFileLocation location = new SourceFileLocation(sourceFile, token); |
1732 if (!location.isValid()) { | 1741 if (!location.isValid()) { |
1733 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( | 1742 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( |
1734 {'offset': token.charOffset, | 1743 {'offset': token.charOffset, |
1735 'fileName': sourceFile.filename, | 1744 'fileName': sourceFile.filename, |
1736 'length': sourceFile.text.length}); | 1745 'length': sourceFile.text.length}); |
1737 } | 1746 } |
1738 return location; | 1747 return location; |
1739 } | 1748 } |
1740 | 1749 |
1741 void visit(Node node) { | 1750 void visit(Node node) { |
1742 if (node != null) node.accept(this); | 1751 if (node != null) node.accept(this); |
1743 } | 1752 } |
1744 | 1753 |
1745 visitBlock(Block node) { | 1754 visitBlock(Block node) { |
1746 for (Link<Node> link = node.statements.nodes; | 1755 for (Link<Node> link = node.statements.nodes; |
1747 !link.isEmpty; | 1756 !link.isEmpty; |
1748 link = link.tail) { | 1757 link = link.tail) { |
1749 visit(link.head); | 1758 visit(link.head); |
(...skipping 25 matching lines...) Expand all Loading... | |
1775 assert(!isAborted()); | 1784 assert(!isAborted()); |
1776 HBasicBlock previousBlock = close(new HGoto()); | 1785 HBasicBlock previousBlock = close(new HGoto()); |
1777 | 1786 |
1778 JumpHandler jumpHandler = createJumpHandler(node); | 1787 JumpHandler jumpHandler = createJumpHandler(node); |
1779 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock( | 1788 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock( |
1780 jumpHandler.target, | 1789 jumpHandler.target, |
1781 jumpHandler.labels()); | 1790 jumpHandler.labels()); |
1782 previousBlock.addSuccessor(loopEntry); | 1791 previousBlock.addSuccessor(loopEntry); |
1783 open(loopEntry); | 1792 open(loopEntry); |
1784 | 1793 |
1785 localsHandler.beginLoopHeader(node, loopEntry); | 1794 localsHandler.beginLoopHeader(loopEntry); |
1786 return jumpHandler; | 1795 return jumpHandler; |
1787 } | 1796 } |
1788 | 1797 |
1789 /** | 1798 /** |
1790 * Ends the loop: | 1799 * Ends the loop: |
1791 * - creates a new block and adds it as successor to the [branchBlock]. | 1800 * - creates a new block and adds it as successor to the [branchBlock] and |
1801 * any blocks that end in break. | |
1792 * - opens the new block (setting as [current]). | 1802 * - opens the new block (setting as [current]). |
1793 * - notifies the locals handler that we're exiting a loop. | 1803 * - notifies the locals handler that we're exiting a loop. |
1804 * [savedLocals] are the locals from the end of the loop condition. | |
1805 * [branchBlock] is the exit (branching) block of the condition. For the | |
1806 * while and for loops this is at the top of the loop. For do-while it is | |
1807 * the end of the body. It is null for degenerate do-while loops that have | |
1808 * no back edge because they abort (throw/return/break in the body and have | |
1809 * no continues). | |
1794 */ | 1810 */ |
1795 void endLoop(HBasicBlock loopEntry, | 1811 void endLoop(HBasicBlock loopEntry, |
1796 HBasicBlock branchBlock, | 1812 HBasicBlock branchBlock, |
1797 JumpHandler jumpHandler, | 1813 JumpHandler jumpHandler, |
1798 LocalsHandler savedLocals) { | 1814 LocalsHandler savedLocals) { |
1799 if (branchBlock == null && !jumpHandler.hasAnyBreak()) return; | |
1800 | |
1801 HBasicBlock loopExitBlock = addNewBlock(); | 1815 HBasicBlock loopExitBlock = addNewBlock(); |
1802 assert(branchBlock == null || branchBlock.successors.length == 1); | 1816 List<LocalsHandler> breakHandlers = <LocalsHandler>[]; |
1803 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 1817 // Collect data for the successors and the phis at each break. |
1804 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 1818 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
1805 breakInstruction.block.addSuccessor(loopExitBlock); | 1819 breakInstruction.block.addSuccessor(loopExitBlock); |
1806 breakLocals.add(locals); | 1820 breakHandlers.add(locals); |
1807 }); | 1821 }); |
1822 // The exit block is a successor of the loop condition if it is reached. | |
1823 // We don't add the successor in the case of a while/for loop that aborts | |
1824 // because the caller of endLoop will be wiring up a special empty else | |
1825 // block instead. | |
1808 if (branchBlock != null) { | 1826 if (branchBlock != null) { |
1809 branchBlock.addSuccessor(loopExitBlock); | 1827 branchBlock.addSuccessor(loopExitBlock); |
1810 } | 1828 } |
1829 // Update the phis at the loop entry with the current values of locals. | |
1830 localsHandler.endLoop(loopEntry); | |
1831 | |
1832 // Start generating code for the exit block. | |
1811 open(loopExitBlock); | 1833 open(loopExitBlock); |
1812 localsHandler.endLoop(loopEntry); | 1834 |
1813 if (!breakLocals.isEmpty) { | 1835 // Create a new localsHandler for the loopExitBlock with the correct phis. |
1814 breakLocals.add(savedLocals); | 1836 if (!breakHandlers.isEmpty) { |
1815 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock); | 1837 if (branchBlock != null) { |
1838 // Add the values of the locals at the end of the condition block to | |
1839 // the phis. These are the values that flow to the exit if the | |
1840 // condition fails. | |
1841 breakHandlers.add(savedLocals); | |
1842 } | |
1843 localsHandler = savedLocals.mergeMultiple(breakHandlers, loopExitBlock); | |
1816 } else { | 1844 } else { |
1817 localsHandler = savedLocals; | 1845 localsHandler = savedLocals; |
1818 } | 1846 } |
1819 } | 1847 } |
1820 | 1848 |
1821 HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) { | 1849 HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) { |
1822 if (statements == null) return null; | 1850 if (statements == null) return null; |
1823 return new HSubGraphBlockInformation(statements); | 1851 return new HSubGraphBlockInformation(statements); |
1824 } | 1852 } |
1825 | 1853 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1863 HLoopInformation loopInfo = current.loopInformation; | 1891 HLoopInformation loopInfo = current.loopInformation; |
1864 HBasicBlock conditionBlock = current; | 1892 HBasicBlock conditionBlock = current; |
1865 if (startBlock == null) startBlock = conditionBlock; | 1893 if (startBlock == null) startBlock = conditionBlock; |
1866 | 1894 |
1867 HInstruction conditionInstruction = condition(); | 1895 HInstruction conditionInstruction = condition(); |
1868 HBasicBlock conditionExitBlock = | 1896 HBasicBlock conditionExitBlock = |
1869 close(new HLoopBranch(conditionInstruction)); | 1897 close(new HLoopBranch(conditionInstruction)); |
1870 SubExpression conditionExpression = | 1898 SubExpression conditionExpression = |
1871 new SubExpression(conditionBlock, conditionExitBlock); | 1899 new SubExpression(conditionBlock, conditionExitBlock); |
1872 | 1900 |
1901 // Save the values of the local variables at the end of the condition | |
1902 // block. These are the values that will flow to the loop exit if the | |
1903 // condition fails. | |
1873 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1904 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1874 | 1905 |
1875 // The body. | 1906 // The body. |
1876 HBasicBlock beginBodyBlock = addNewBlock(); | 1907 HBasicBlock beginBodyBlock = addNewBlock(); |
1877 conditionExitBlock.addSuccessor(beginBodyBlock); | 1908 conditionExitBlock.addSuccessor(beginBodyBlock); |
1878 open(beginBodyBlock); | 1909 open(beginBodyBlock); |
1879 | 1910 |
1880 localsHandler.enterLoopBody(loop); | 1911 localsHandler.enterLoopBody(loop); |
1881 body(); | 1912 body(); |
1882 | 1913 |
1883 SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock); | 1914 SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock); |
1884 HBasicBlock bodyBlock = current; | 1915 HBasicBlock bodyBlock = current; |
1885 if (current != null) close(new HGoto()); | 1916 if (current != null) close(new HGoto()); |
1886 | 1917 |
1887 SubExpression updateGraph; | 1918 SubExpression updateGraph; |
1888 | 1919 |
1889 // Check that the loop has at least one back-edge. | 1920 bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null; |
1890 if (jumpHandler.hasAnyContinue() || bodyBlock != null) { | 1921 if (!loopIsDegenerate) { |
1891 // Update. | 1922 // Update. |
1892 // We create an update block, even when we are in a while loop. There the | 1923 // We create an update block, even when we are in a while loop. There the |
1893 // update block is the jump-target for continue statements. We could avoid | 1924 // update block is the jump-target for continue statements. We could avoid |
1894 // the creation if there is no continue, but for now we always create it. | 1925 // the creation if there is no continue, but for now we always create it. |
1895 HBasicBlock updateBlock = addNewBlock(); | 1926 HBasicBlock updateBlock = addNewBlock(); |
1896 | 1927 |
1897 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1928 List<LocalsHandler> continueHandlers = <LocalsHandler>[]; |
1898 jumpHandler.forEachContinue((HContinue instruction, | 1929 jumpHandler.forEachContinue((HContinue instruction, |
1899 LocalsHandler locals) { | 1930 LocalsHandler locals) { |
1900 instruction.block.addSuccessor(updateBlock); | 1931 instruction.block.addSuccessor(updateBlock); |
1901 continueLocals.add(locals); | 1932 continueHandlers.add(locals); |
1902 }); | 1933 }); |
1903 | 1934 |
1904 | 1935 |
1905 if (bodyBlock != null) { | 1936 if (bodyBlock != null) { |
1906 continueLocals.add(localsHandler); | 1937 continueHandlers.add(localsHandler); |
1907 bodyBlock.addSuccessor(updateBlock); | 1938 bodyBlock.addSuccessor(updateBlock); |
1908 } | 1939 } |
1909 | 1940 |
1910 open(updateBlock); | 1941 open(updateBlock); |
1911 localsHandler = | 1942 localsHandler = |
1912 continueLocals[0].mergeMultiple(continueLocals, updateBlock); | 1943 continueHandlers[0].mergeMultiple(continueHandlers, updateBlock); |
1913 | 1944 |
1914 HLabeledBlockInformation labelInfo; | 1945 HLabeledBlockInformation labelInfo; |
1915 List<LabelElement> labels = jumpHandler.labels(); | 1946 List<LabelElement> labels = jumpHandler.labels(); |
1916 TargetElement target = elements[loop]; | 1947 TargetElement target = elements[loop]; |
1917 if (!labels.isEmpty) { | 1948 if (!labels.isEmpty) { |
1918 beginBodyBlock.setBlockFlow( | 1949 beginBodyBlock.setBlockFlow( |
1919 new HLabeledBlockInformation( | 1950 new HLabeledBlockInformation( |
1920 new HSubGraphBlockInformation(bodyGraph), | 1951 new HSubGraphBlockInformation(bodyGraph), |
1921 jumpHandler.labels(), | 1952 jumpHandler.labels(), |
1922 isContinue: true), | 1953 isContinue: true), |
1923 updateBlock); | 1954 updateBlock); |
1924 } else if (target != null && target.isContinueTarget) { | 1955 } else if (target != null && target.isContinueTarget) { |
1925 beginBodyBlock.setBlockFlow( | 1956 beginBodyBlock.setBlockFlow( |
1926 new HLabeledBlockInformation.implicit( | 1957 new HLabeledBlockInformation.implicit( |
1927 new HSubGraphBlockInformation(bodyGraph), | 1958 new HSubGraphBlockInformation(bodyGraph), |
1928 target, | 1959 target, |
1929 isContinue: true), | 1960 isContinue: true), |
1930 updateBlock); | 1961 updateBlock); |
1931 } | 1962 } |
1932 | 1963 |
1933 localsHandler.enterLoopUpdates(loop); | 1964 localsHandler.enterLoopUpdates(loop); |
1934 | 1965 |
1935 update(); | 1966 update(); |
1936 | 1967 |
1937 HBasicBlock updateEndBlock = close(new HGoto()); | 1968 HBasicBlock updateEndBlock = close(new HGoto()); |
1938 // The back-edge completing the cycle. | 1969 // The back-edge completing the cycle. |
1939 updateEndBlock.addSuccessor(conditionBlock); | 1970 updateEndBlock.addSuccessor(conditionBlock); |
1940 updateGraph = new SubExpression(updateBlock, updateEndBlock); | 1971 updateGraph = new SubExpression(updateBlock, updateEndBlock); |
1941 } | |
1942 | 1972 |
1943 if (jumpHandler.hasAnyContinue() || bodyBlock != null) { | |
1944 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); | 1973 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
1974 | |
1945 conditionBlock.postProcessLoopHeader(); | 1975 conditionBlock.postProcessLoopHeader(); |
1946 HLoopBlockInformation info = | 1976 HLoopBlockInformation info = |
1947 new HLoopBlockInformation( | 1977 new HLoopBlockInformation( |
1948 HLoopBlockInformation.loopType(loop), | 1978 HLoopBlockInformation.loopType(loop), |
1949 wrapExpressionGraph(initializerGraph), | 1979 wrapExpressionGraph(initializerGraph), |
1950 wrapExpressionGraph(conditionExpression), | 1980 wrapExpressionGraph(conditionExpression), |
1951 wrapStatementGraph(bodyGraph), | 1981 wrapStatementGraph(bodyGraph), |
1952 wrapExpressionGraph(updateGraph), | 1982 wrapExpressionGraph(updateGraph), |
1953 conditionBlock.loopInformation.target, | 1983 conditionBlock.loopInformation.target, |
1954 conditionBlock.loopInformation.labels, | 1984 conditionBlock.loopInformation.labels, |
1955 sourceFileLocationForBeginToken(loop), | 1985 sourceFileLocationForBeginToken(loop), |
1956 sourceFileLocationForEndToken(loop)); | 1986 sourceFileLocationForEndToken(loop)); |
1957 | 1987 |
1958 startBlock.setBlockFlow(info, current); | 1988 startBlock.setBlockFlow(info, current); |
1959 loopInfo.loopBlockInformation = info; | 1989 loopInfo.loopBlockInformation = info; |
1960 } else { | 1990 } else { |
1961 // There is no back edge for the loop, so we turn the code into: | 1991 // The body of the for/while loop always aborts, so there is no back edge. |
1992 // We turn the code into: | |
1962 // if (condition) { | 1993 // if (condition) { |
1963 // body; | 1994 // body; |
1964 // } else { | 1995 // } else { |
1965 // // We always create an empty else block to avoid critical edges. | 1996 // // We always create an empty else block to avoid critical edges. |
1966 // } | 1997 // } |
1967 // | 1998 // |
1968 // If there is any break in the body, we attach a synthetic | 1999 // If there is any break in the body, we attach a synthetic |
1969 // label to the if. | 2000 // label to the if. |
1970 HBasicBlock elseBlock = addNewBlock(); | 2001 HBasicBlock elseBlock = addNewBlock(); |
1971 open(elseBlock); | 2002 open(elseBlock); |
1972 close(new HGoto()); | 2003 close(new HGoto()); |
1973 endLoop(conditionBlock, null, jumpHandler, savedLocals); | 2004 // Pass the elseBlock as the branchBlock, because that's the block we go |
2005 // to just before leaving the 'loop'. | |
2006 endLoop(conditionBlock, elseBlock, jumpHandler, savedLocals); | |
1974 | 2007 |
1975 // [endLoop] will not create an exit block if there are no | |
1976 // breaks. | |
1977 if (current == null) open(addNewBlock()); | |
1978 elseBlock.addSuccessor(current); | |
1979 SubGraph elseGraph = new SubGraph(elseBlock, elseBlock); | 2008 SubGraph elseGraph = new SubGraph(elseBlock, elseBlock); |
1980 // Remove the loop information attached to the header. | 2009 // Remove the loop information attached to the header. |
1981 conditionBlock.loopInformation = null; | 2010 conditionBlock.loopInformation = null; |
1982 | 2011 |
1983 // Remove the [HLoopBranch] instruction and replace it with | 2012 // Remove the [HLoopBranch] instruction and replace it with |
1984 // [HIf]. | 2013 // [HIf]. |
1985 HInstruction condition = conditionExitBlock.last.inputs[0]; | 2014 HInstruction condition = conditionExitBlock.last.inputs[0]; |
1986 conditionExitBlock.addAtExit(new HIf(condition)); | 2015 conditionExitBlock.addAtExit(new HIf(condition)); |
1987 conditionExitBlock.addSuccessor(elseBlock); | 2016 conditionExitBlock.addSuccessor(elseBlock); |
1988 conditionExitBlock.remove(conditionExitBlock.last); | 2017 conditionExitBlock.remove(conditionExitBlock.last); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2092 HBasicBlock bodyExitBlock; | 2121 HBasicBlock bodyExitBlock; |
2093 bool isAbortingBody = false; | 2122 bool isAbortingBody = false; |
2094 if (current != null) { | 2123 if (current != null) { |
2095 bodyExitBlock = close(new HGoto()); | 2124 bodyExitBlock = close(new HGoto()); |
2096 } else { | 2125 } else { |
2097 isAbortingBody = true; | 2126 isAbortingBody = true; |
2098 bodyExitBlock = lastOpenedBlock; | 2127 bodyExitBlock = lastOpenedBlock; |
2099 } | 2128 } |
2100 | 2129 |
2101 SubExpression conditionExpression; | 2130 SubExpression conditionExpression; |
2102 HBasicBlock conditionEndBlock; | 2131 bool loopIsDegenerate = isAbortingBody && !hasContinues; |
2103 if (!isAbortingBody || hasContinues) { | 2132 if (!loopIsDegenerate) { |
2104 HBasicBlock conditionBlock = addNewBlock(); | 2133 HBasicBlock conditionBlock = addNewBlock(); |
2105 | 2134 |
2106 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 2135 List<LocalsHandler> continueHandlers = <LocalsHandler>[]; |
2107 jumpHandler.forEachContinue((HContinue instruction, | 2136 jumpHandler.forEachContinue((HContinue instruction, |
2108 LocalsHandler locals) { | 2137 LocalsHandler locals) { |
2109 instruction.block.addSuccessor(conditionBlock); | 2138 instruction.block.addSuccessor(conditionBlock); |
2110 continueLocals.add(locals); | 2139 continueHandlers.add(locals); |
2111 }); | 2140 }); |
2112 | 2141 |
2113 if (!isAbortingBody) { | 2142 if (!isAbortingBody) { |
2114 bodyExitBlock.addSuccessor(conditionBlock); | 2143 bodyExitBlock.addSuccessor(conditionBlock); |
2115 } | 2144 } |
2116 | 2145 |
2117 if (!continueLocals.isEmpty) { | 2146 if (!continueHandlers.isEmpty) { |
2118 if (!isAbortingBody) continueLocals.add(localsHandler); | 2147 if (!isAbortingBody) continueHandlers.add(localsHandler); |
2119 localsHandler = | 2148 localsHandler = |
2120 savedLocals.mergeMultiple(continueLocals, conditionBlock); | 2149 savedLocals.mergeMultiple(continueHandlers, conditionBlock); |
2121 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 2150 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
2122 List<LabelElement> labels = jumpHandler.labels(); | 2151 List<LabelElement> labels = jumpHandler.labels(); |
2123 HSubGraphBlockInformation bodyInfo = | 2152 HSubGraphBlockInformation bodyInfo = |
2124 new HSubGraphBlockInformation(bodyGraph); | 2153 new HSubGraphBlockInformation(bodyGraph); |
2125 HLabeledBlockInformation info; | 2154 HLabeledBlockInformation info; |
2126 if (!labels.isEmpty) { | 2155 if (!labels.isEmpty) { |
2127 info = new HLabeledBlockInformation(bodyInfo, labels, | 2156 info = new HLabeledBlockInformation(bodyInfo, labels, |
2128 isContinue: true); | 2157 isContinue: true); |
2129 } else { | 2158 } else { |
2130 info = new HLabeledBlockInformation.implicit(bodyInfo, target, | 2159 info = new HLabeledBlockInformation.implicit(bodyInfo, target, |
2131 isContinue: true); | 2160 isContinue: true); |
2132 } | 2161 } |
2133 bodyEntryBlock.setBlockFlow(info, conditionBlock); | 2162 bodyEntryBlock.setBlockFlow(info, conditionBlock); |
2134 } | 2163 } |
2135 open(conditionBlock); | 2164 open(conditionBlock); |
2136 | 2165 |
2137 visit(node.condition); | 2166 visit(node.condition); |
2138 assert(!isAborted()); | 2167 assert(!isAborted()); |
2139 HInstruction conditionInstruction = popBoolified(); | 2168 HInstruction conditionInstruction = popBoolified(); |
2140 conditionEndBlock = close( | 2169 HBasicBlock conditionEndBlock = close( |
2141 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); | 2170 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); |
2142 | 2171 |
2143 HBasicBlock avoidCriticalEdge = addNewBlock(); | 2172 HBasicBlock avoidCriticalEdge = addNewBlock(); |
2144 conditionEndBlock.addSuccessor(avoidCriticalEdge); | 2173 conditionEndBlock.addSuccessor(avoidCriticalEdge); |
2145 open(avoidCriticalEdge); | 2174 open(avoidCriticalEdge); |
2146 close(new HGoto()); | 2175 close(new HGoto()); |
2147 avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge. | 2176 avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge. |
2148 | 2177 |
2149 conditionExpression = | 2178 conditionExpression = |
2150 new SubExpression(conditionBlock, conditionEndBlock); | 2179 new SubExpression(conditionBlock, conditionEndBlock); |
2151 } | |
2152 | 2180 |
2153 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); | 2181 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); |
2154 if (!isAbortingBody || hasContinues) { | 2182 |
2155 loopEntryBlock.postProcessLoopHeader(); | 2183 loopEntryBlock.postProcessLoopHeader(); |
2156 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); | 2184 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); |
2157 HLoopBlockInformation loopBlockInfo = | 2185 HLoopBlockInformation loopBlockInfo = |
2158 new HLoopBlockInformation( | 2186 new HLoopBlockInformation( |
2159 HLoopBlockInformation.DO_WHILE_LOOP, | 2187 HLoopBlockInformation.DO_WHILE_LOOP, |
2160 null, | 2188 null, |
2161 wrapExpressionGraph(conditionExpression), | 2189 wrapExpressionGraph(conditionExpression), |
2162 wrapStatementGraph(bodyGraph), | 2190 wrapStatementGraph(bodyGraph), |
2163 null, | 2191 null, |
2164 loopEntryBlock.loopInformation.target, | 2192 loopEntryBlock.loopInformation.target, |
2165 loopEntryBlock.loopInformation.labels, | 2193 loopEntryBlock.loopInformation.labels, |
2166 sourceFileLocationForBeginToken(node), | 2194 sourceFileLocationForBeginToken(node), |
2167 sourceFileLocationForEndToken(node)); | 2195 sourceFileLocationForEndToken(node)); |
2168 loopEntryBlock.setBlockFlow(loopBlockInfo, current); | 2196 loopEntryBlock.setBlockFlow(loopBlockInfo, current); |
2169 loopInfo.loopBlockInformation = loopBlockInfo; | 2197 loopInfo.loopBlockInformation = loopBlockInfo; |
2170 } else { | 2198 } else { |
2171 // If the loop has no back edge, we remove the loop information | 2199 // Since the loop has no back edge, we remove the loop information on the |
2172 // on the header. | 2200 // header. |
2173 loopEntryBlock.loopInformation = null; | 2201 loopEntryBlock.loopInformation = null; |
2174 | 2202 |
2175 // If the body of the loop has any break, we attach a | |
2176 // synthesized label to the body. | |
2177 if (jumpHandler.hasAnyBreak()) { | 2203 if (jumpHandler.hasAnyBreak()) { |
2204 // Null branchBlock because the body of the do-while loop always aborts, | |
2205 // so we never get to the condition. | |
2206 endLoop(loopEntryBlock, null, jumpHandler, localsHandler); | |
2207 | |
2208 // Since the body of the loop has a break, we attach a synthesized label | |
2209 // to the body. | |
2178 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 2210 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
2179 TargetElement target = elements[node]; | 2211 TargetElement target = elements[node]; |
2180 LabelElement label = target.addLabel(null, 'loop'); | 2212 LabelElement label = target.addLabel(null, 'loop'); |
2181 label.setBreakTarget(); | 2213 label.setBreakTarget(); |
2182 HLabeledBlockInformation info = new HLabeledBlockInformation( | 2214 HLabeledBlockInformation info = new HLabeledBlockInformation( |
2183 new HSubGraphBlockInformation(bodyGraph), <LabelElement>[label]); | 2215 new HSubGraphBlockInformation(bodyGraph), <LabelElement>[label]); |
2184 loopEntryBlock.setBlockFlow(info, current); | 2216 loopEntryBlock.setBlockFlow(info, current); |
2185 jumpHandler.forEachBreak((HBreak breakInstruction, _) { | 2217 jumpHandler.forEachBreak((HBreak breakInstruction, _) { |
2186 HBasicBlock block = breakInstruction.block; | 2218 HBasicBlock block = breakInstruction.block; |
2187 block.addAtExit(new HBreak.toLabel(label)); | 2219 block.addAtExit(new HBreak.toLabel(label)); |
(...skipping 1882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4070 } | 4102 } |
4071 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); | 4103 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); |
4072 assert(targetElement.isBreakTarget); | 4104 assert(targetElement.isBreakTarget); |
4073 JumpHandler handler = new JumpHandler(this, targetElement); | 4105 JumpHandler handler = new JumpHandler(this, targetElement); |
4074 // Introduce a new basic block. | 4106 // Introduce a new basic block. |
4075 HBasicBlock entryBlock = openNewBlock(); | 4107 HBasicBlock entryBlock = openNewBlock(); |
4076 visit(body); | 4108 visit(body); |
4077 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); | 4109 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); |
4078 | 4110 |
4079 HBasicBlock joinBlock = graph.addNewBlock(); | 4111 HBasicBlock joinBlock = graph.addNewBlock(); |
4080 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 4112 List<LocalsHandler> breakHandlers = <LocalsHandler>[]; |
4081 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 4113 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
4082 breakInstruction.block.addSuccessor(joinBlock); | 4114 breakInstruction.block.addSuccessor(joinBlock); |
4083 breakLocals.add(locals); | 4115 breakHandlers.add(locals); |
4084 }); | 4116 }); |
4085 bool hasBreak = breakLocals.length > 0; | 4117 bool hasBreak = breakHandlers.length > 0; |
4086 if (!isAborted()) { | 4118 if (!isAborted()) { |
4087 goto(current, joinBlock); | 4119 goto(current, joinBlock); |
4088 breakLocals.add(localsHandler); | 4120 breakHandlers.add(localsHandler); |
4089 } | 4121 } |
4090 open(joinBlock); | 4122 open(joinBlock); |
4091 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); | 4123 localsHandler = beforeLocals.mergeMultiple(breakHandlers, joinBlock); |
4092 | 4124 |
4093 if (hasBreak) { | 4125 if (hasBreak) { |
4094 // There was at least one reachable break, so the label is needed. | 4126 // There was at least one reachable break, so the label is needed. |
4095 entryBlock.setBlockFlow( | 4127 entryBlock.setBlockFlow( |
4096 new HLabeledBlockInformation(new HSubGraphBlockInformation(bodyGraph), | 4128 new HLabeledBlockInformation(new HSubGraphBlockInformation(bodyGraph), |
4097 handler.labels()), | 4129 handler.labels()), |
4098 joinBlock); | 4130 joinBlock); |
4099 } | 4131 } |
4100 handler.close(); | 4132 handler.close(); |
4101 } | 4133 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4144 | 4176 |
4145 Link<Node> cases = node.cases.nodes; | 4177 Link<Node> cases = node.cases.nodes; |
4146 JumpHandler jumpHandler = createJumpHandler(node); | 4178 JumpHandler jumpHandler = createJumpHandler(node); |
4147 | 4179 |
4148 buildSwitchCases(cases, expression); | 4180 buildSwitchCases(cases, expression); |
4149 | 4181 |
4150 HBasicBlock lastBlock = lastOpenedBlock; | 4182 HBasicBlock lastBlock = lastOpenedBlock; |
4151 | 4183 |
4152 // Create merge block for break targets. | 4184 // Create merge block for break targets. |
4153 HBasicBlock joinBlock = new HBasicBlock(); | 4185 HBasicBlock joinBlock = new HBasicBlock(); |
4154 List<LocalsHandler> caseLocals = <LocalsHandler>[]; | 4186 List<LocalsHandler> caseHandlers = <LocalsHandler>[]; |
4155 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { | 4187 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { |
4156 instruction.block.addSuccessor(joinBlock); | 4188 instruction.block.addSuccessor(joinBlock); |
4157 caseLocals.add(locals); | 4189 caseHandlers.add(locals); |
4158 }); | 4190 }); |
4159 if (!isAborted()) { | 4191 if (!isAborted()) { |
4160 // The current flow is only aborted if the switch has a default that | 4192 // The current flow is only aborted if the switch has a default that |
4161 // aborts (all previous cases must abort, and if there is no default, | 4193 // aborts (all previous cases must abort, and if there is no default, |
4162 // it's possible to miss all the cases). | 4194 // it's possible to miss all the cases). |
4163 caseLocals.add(localsHandler); | 4195 caseHandlers.add(localsHandler); |
4164 goto(current, joinBlock); | 4196 goto(current, joinBlock); |
4165 } | 4197 } |
4166 if (caseLocals.length != 0) { | 4198 if (caseHandlers.length != 0) { |
4167 graph.addBlock(joinBlock); | 4199 graph.addBlock(joinBlock); |
4168 open(joinBlock); | 4200 open(joinBlock); |
4169 if (caseLocals.length == 1) { | 4201 if (caseHandlers.length == 1) { |
4170 localsHandler = caseLocals[0]; | 4202 localsHandler = caseHandlers[0]; |
4171 } else { | 4203 } else { |
4172 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock); | 4204 localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock); |
4173 } | 4205 } |
4174 } else { | 4206 } else { |
4175 // The joinblock is not used. | 4207 // The joinblock is not used. |
4176 joinBlock = null; | 4208 joinBlock = null; |
4177 } | 4209 } |
4178 startBlock.setBlockFlow( | 4210 startBlock.setBlockFlow( |
4179 new HLabeledBlockInformation.implicit( | 4211 new HLabeledBlockInformation.implicit( |
4180 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)), | 4212 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)), |
4181 elements[node]), | 4213 elements[node]), |
4182 joinBlock); | 4214 joinBlock); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4283 HInstruction error = pop(); | 4315 HInstruction error = pop(); |
4284 close(new HThrow(error)); | 4316 close(new HThrow(error)); |
4285 } | 4317 } |
4286 statements.add( | 4318 statements.add( |
4287 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); | 4319 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); |
4288 } | 4320 } |
4289 | 4321 |
4290 // Add a join-block if necessary. | 4322 // Add a join-block if necessary. |
4291 // We create [joinBlock] early, and then go through the cases that might | 4323 // We create [joinBlock] early, and then go through the cases that might |
4292 // want to jump to it. In each case, if we add [joinBlock] as a successor | 4324 // want to jump to it. In each case, if we add [joinBlock] as a successor |
4293 // of another block, we also add an element to [caseLocals] that is used | 4325 // of another block, we also add an element to [caseHandlers] that is used |
4294 // to create the phis in [joinBlock]. | 4326 // to create the phis in [joinBlock]. |
4295 // If we never jump to the join block, [caseLocals] will stay empty, and | 4327 // If we never jump to the join block, [caseHandlers] will stay empty, and |
4296 // the join block is never added to the graph. | 4328 // the join block is never added to the graph. |
4297 HBasicBlock joinBlock = new HBasicBlock(); | 4329 HBasicBlock joinBlock = new HBasicBlock(); |
4298 List<LocalsHandler> caseLocals = <LocalsHandler>[]; | 4330 List<LocalsHandler> caseHandlers = <LocalsHandler>[]; |
4299 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { | 4331 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { |
4300 instruction.block.addSuccessor(joinBlock); | 4332 instruction.block.addSuccessor(joinBlock); |
4301 caseLocals.add(locals); | 4333 caseHandlers.add(locals); |
4302 }); | 4334 }); |
4303 if (!isAborted()) { | 4335 if (!isAborted()) { |
4304 current.close(new HGoto()); | 4336 current.close(new HGoto()); |
4305 lastOpenedBlock.addSuccessor(joinBlock); | 4337 lastOpenedBlock.addSuccessor(joinBlock); |
4306 caseLocals.add(localsHandler); | 4338 caseHandlers.add(localsHandler); |
4307 } | 4339 } |
4308 if (!hasDefault) { | 4340 if (!hasDefault) { |
4309 // The current flow is only aborted if the switch has a default that | 4341 // The current flow is only aborted if the switch has a default that |
4310 // aborts (all previous cases must abort, and if there is no default, | 4342 // aborts (all previous cases must abort, and if there is no default, |
4311 // it's possible to miss all the cases). | 4343 // it's possible to miss all the cases). |
4312 expressionEnd.addSuccessor(joinBlock); | 4344 expressionEnd.addSuccessor(joinBlock); |
4313 caseLocals.add(savedLocals); | 4345 caseHandlers.add(savedLocals); |
4314 } | 4346 } |
4315 assert(caseLocals.length == joinBlock.predecessors.length); | 4347 assert(caseHandlers.length == joinBlock.predecessors.length); |
4316 if (caseLocals.length != 0) { | 4348 if (caseHandlers.length != 0) { |
4317 graph.addBlock(joinBlock); | 4349 graph.addBlock(joinBlock); |
4318 open(joinBlock); | 4350 open(joinBlock); |
4319 if (caseLocals.length == 1) { | 4351 if (caseHandlers.length == 1) { |
4320 localsHandler = caseLocals[0]; | 4352 localsHandler = caseHandlers[0]; |
4321 } else { | 4353 } else { |
4322 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock); | 4354 localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock); |
4323 } | 4355 } |
4324 } else { | 4356 } else { |
4325 // The joinblock is not used. | 4357 // The joinblock is not used. |
4326 joinBlock = null; | 4358 joinBlock = null; |
4327 } | 4359 } |
4328 | 4360 |
4329 HSubExpressionBlockInformation expressionInfo = | 4361 HSubExpressionBlockInformation expressionInfo = |
4330 new HSubExpressionBlockInformation(new SubExpression(expressionStart, | 4362 new HSubExpressionBlockInformation(new SubExpression(expressionStart, |
4331 expressionEnd)); | 4363 expressionEnd)); |
4332 expressionStart.setBlockFlow( | 4364 expressionStart.setBlockFlow( |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4865 } | 4897 } |
4866 node.visitChildren(this); | 4898 node.visitChildren(this); |
4867 seenReturn = true; | 4899 seenReturn = true; |
4868 } | 4900 } |
4869 | 4901 |
4870 void visitTryStatement(Node node) { | 4902 void visitTryStatement(Node node) { |
4871 if (!registerNode()) return; | 4903 if (!registerNode()) return; |
4872 tooDifficult = true; | 4904 tooDifficult = true; |
4873 } | 4905 } |
4874 | 4906 |
4875 void visitThrow(Node node) { | 4907 void visitThrow(Node node) { |
ngeoffray
2013/04/07 09:48:50
Why is that restriction not removed? Is that not w
| |
4876 if (!registerNode()) return; | 4908 if (!registerNode()) return; |
4877 tooDifficult = true; | 4909 tooDifficult = true; |
4878 } | 4910 } |
4879 } | 4911 } |
4880 | 4912 |
4881 class InliningState { | 4913 class InliningState { |
4882 /** | 4914 /** |
4883 * Documentation wanted -- johnniwinther | 4915 * Documentation wanted -- johnniwinther |
4884 * | 4916 * |
4885 * Invariant: [function] must be an implementation element. | 4917 * Invariant: [function] must be an implementation element. |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5129 new HSubGraphBlockInformation(elseBranch.graph)); | 5161 new HSubGraphBlockInformation(elseBranch.graph)); |
5130 | 5162 |
5131 HBasicBlock conditionStartBlock = conditionBranch.block; | 5163 HBasicBlock conditionStartBlock = conditionBranch.block; |
5132 conditionStartBlock.setBlockFlow(info, joinBlock); | 5164 conditionStartBlock.setBlockFlow(info, joinBlock); |
5133 SubGraph conditionGraph = conditionBranch.graph; | 5165 SubGraph conditionGraph = conditionBranch.graph; |
5134 HIf branch = conditionGraph.end.last; | 5166 HIf branch = conditionGraph.end.last; |
5135 assert(branch is HIf); | 5167 assert(branch is HIf); |
5136 branch.blockInformation = conditionStartBlock.blockFlow; | 5168 branch.blockInformation = conditionStartBlock.blockFlow; |
5137 } | 5169 } |
5138 } | 5170 } |
OLD | NEW |