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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart

Issue 1201983002: Implement try/finally by inlining the finally code. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Run all the finally blocks. Created 5 years, 6 months 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 library dart2js.ir_builder; 5 library dart2js.ir_builder;
6 6
7 import '../compile_time_constants.dart' show BackendConstantEnvironment; 7 import '../compile_time_constants.dart' show BackendConstantEnvironment;
8 import '../constants/constant_system.dart'; 8 import '../constants/constant_system.dart';
9 import '../constants/expressions.dart'; 9 import '../constants/expressions.dart';
10 import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue; 10 import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 /// give a handle to the continuation and its environment. 124 /// give a handle to the continuation and its environment.
125 abstract class JumpCollector { 125 abstract class JumpCollector {
126 final JumpTarget target; 126 final JumpTarget target;
127 127
128 ir.Continuation _continuation = null; 128 ir.Continuation _continuation = null;
129 final Environment _continuationEnvironment; 129 final Environment _continuationEnvironment;
130 130
131 final List<Iterable<LocalVariableElement>> _boxedTryVariables = 131 final List<Iterable<LocalVariableElement>> _boxedTryVariables =
132 <Iterable<LocalVariableElement>>[]; 132 <Iterable<LocalVariableElement>>[];
133 133
134 /// A stack of all the enclosing finally blocks up to the target of the jump.
135 ///
136 /// There are null entries which correspond to try/catch (no finally).
137 final List<SubbuildFunction> _finallyBlocks = <SubbuildFunction>[];
138
134 JumpCollector(this._continuationEnvironment, this.target); 139 JumpCollector(this._continuationEnvironment, this.target);
135 140
136 /// True if the collector has not recorded any jumps to its continuation. 141 /// True if the collector has not recorded any jumps to its continuation.
137 bool get isEmpty; 142 bool get isEmpty;
138 143
139 /// The continuation encapsulated by this collector. 144 /// The continuation encapsulated by this collector.
140 ir.Continuation get continuation; 145 ir.Continuation get continuation;
141 146
142 /// The compile-time environment to be used for translating code in the body 147 /// The compile-time environment to be used for translating code in the body
143 /// of the continuation. 148 /// of the continuation.
144 Environment get environment; 149 Environment get environment;
145 150
146 /// Emit a jump to the continuation for a given [IrBuilder]. 151 /// Emit a jump to the continuation for a given [IrBuilder].
147 void addJump(IrBuilder builder); 152 void addJump(IrBuilder builder);
148 153
149 /// Add a set of variables that were boxed on entry to a try block. 154 /// Add a set of variables that were boxed on entry to a try block.
150 /// 155 ///
151 /// All jumps from a try block to targets outside have to unbox the 156 /// All jumps from a try block to targets outside have to unbox the
152 /// variables that were boxed on entry before invoking the target 157 /// variables that were boxed on entry before invoking the target
153 /// continuation. Call this function before translating a try block and 158 /// continuation. Call this function before translating a try block and
154 /// call [leaveTry] after translating it. 159 /// call [leaveTry] after translating it.
155 void enterTry(Iterable<LocalVariableElement> boxedOnEntry) { 160 void enterTry(Iterable<LocalVariableElement> boxedOnEntry,
161 [SubbuildFunction buildFinallyBlock]) {
156 // The boxed variables are maintained as a stack to make leaving easy. 162 // The boxed variables are maintained as a stack to make leaving easy.
157 _boxedTryVariables.add(boxedOnEntry); 163 _boxedTryVariables.add(boxedOnEntry);
164 _finallyBlocks.add(buildFinallyBlock);
158 } 165 }
159 166
160 /// Remove the most recently added set of variables boxed on entry to a try 167 /// Remove the most recently added set of variables boxed on entry to a try
161 /// block. 168 /// block.
162 /// 169 ///
163 /// Call [enterTry] before translating a try block and call this function 170 /// Call [enterTry] before translating a try block and call this function
164 /// after translating it. 171 /// after translating it.
165 void leaveTry() { 172 void leaveTry() {
166 _boxedTryVariables.removeLast(); 173 _boxedTryVariables.removeLast();
174 _finallyBlocks.removeLast();
167 } 175 }
168 176
169 void _buildTryExit(IrBuilder builder) { 177 void _buildTryExit(IrBuilder builder) {
170 for (Iterable<LocalVariableElement> boxedOnEntry in _boxedTryVariables) { 178 for (Iterable<LocalVariableElement> boxedOnEntry in _boxedTryVariables) {
171 for (LocalVariableElement variable in boxedOnEntry) { 179 for (LocalVariableElement variable in boxedOnEntry) {
172 assert(builder.isInMutableVariable(variable)); 180 assert(builder.isInMutableVariable(variable));
173 ir.Primitive value = builder.buildLocalVariableGet(variable); 181 ir.Primitive value = builder.buildLocalVariableGet(variable);
174 builder.environment.update(variable, value); 182 builder.environment.update(variable, value);
175 } 183 }
176 } 184 }
185 for (SubbuildFunction buildFinallyBlock in _finallyBlocks.reversed) {
186 if (buildFinallyBlock != null) buildFinallyBlock(builder);
187 }
177 } 188 }
178 } 189 }
179 190
180 /// A class to collect 'forward' jumps. 191 /// A class to collect 'forward' jumps.
181 /// 192 ///
182 /// A forward jump to a continuation in the sense of the CPS translation is 193 /// A forward jump to a continuation in the sense of the CPS translation is
183 /// a jump where the jump is emitted before any code in the body of the 194 /// a jump where the jump is emitted before any code in the body of the
184 /// continuation is translated. They have the property that continuation 195 /// continuation is translated. They have the property that continuation
185 /// parameters and the environment for the translation of the body can be 196 /// parameters and the environment for the translation of the body can be
186 /// determined based on the invocations, before translating the body. A 197 /// determined based on the invocations, before translating the body. A
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 final BackendConstantEnvironment constants; 403 final BackendConstantEnvironment constants;
393 404
394 ConstantSystem get constantSystem => constants.constantSystem; 405 ConstantSystem get constantSystem => constants.constantSystem;
395 406
396 /// A stack of collectors for breaks. 407 /// A stack of collectors for breaks.
397 final List<JumpCollector> breakCollectors = <JumpCollector>[]; 408 final List<JumpCollector> breakCollectors = <JumpCollector>[];
398 409
399 /// A stack of collectors for continues. 410 /// A stack of collectors for continues.
400 final List<JumpCollector> continueCollectors = <JumpCollector>[]; 411 final List<JumpCollector> continueCollectors = <JumpCollector>[];
401 412
413 /// A stack of enclosing finally blocks, used when translating return.
414 final List<SubbuildFunction> finallyBlocks = <SubbuildFunction>[];
415
402 final List<ConstDeclaration> localConstants = <ConstDeclaration>[]; 416 final List<ConstDeclaration> localConstants = <ConstDeclaration>[];
403 417
404 final ExecutableElement currentElement; 418 final ExecutableElement currentElement;
405 419
406 final ir.Continuation returnContinuation = new ir.Continuation.retrn(); 420 final ir.Continuation returnContinuation = new ir.Continuation.retrn();
407 ir.Parameter _thisParameter; 421 ir.Parameter _thisParameter;
408 ir.Parameter enclosingMethodThisParameter; 422 ir.Parameter enclosingMethodThisParameter;
409 423
410 final List<ir.Parameter> functionParameters = <ir.Parameter>[]; 424 final List<ir.Parameter> functionParameters = <ir.Parameter>[];
411 425
(...skipping 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1724 /// 1738 ///
1725 /// [tryInfo] provides information on local variables declared and boxed 1739 /// [tryInfo] provides information on local variables declared and boxed
1726 /// within this try statement. 1740 /// within this try statement.
1727 /// [buildTryBlock] builds the try block. 1741 /// [buildTryBlock] builds the try block.
1728 /// [catchClauseInfos] provides access to the catch type, exception variable, 1742 /// [catchClauseInfos] provides access to the catch type, exception variable,
1729 /// and stack trace variable, and a function for building the catch block. 1743 /// and stack trace variable, and a function for building the catch block.
1730 void buildTry( 1744 void buildTry(
1731 {TryStatementInfo tryStatementInfo, 1745 {TryStatementInfo tryStatementInfo,
1732 SubbuildFunction buildTryBlock, 1746 SubbuildFunction buildTryBlock,
1733 List<CatchClauseInfo> catchClauseInfos: const <CatchClauseInfo>[], 1747 List<CatchClauseInfo> catchClauseInfos: const <CatchClauseInfo>[],
1748 SubbuildFunction buildFinallyBlock,
1734 ClosureClassMap closureClassMap}) { 1749 ClosureClassMap closureClassMap}) {
1735 assert(isOpen); 1750 assert(isOpen);
1736 1751
1737 // Catch handlers are in scope for their body. The CPS translation of 1752 // Catch handlers are in scope for their body. The CPS translation of
1738 // [[try tryBlock catch (e) catchBlock; successor]] is: 1753 // [[try tryBlock catch (e) catchBlock; successor]] is:
1739 // 1754 //
1740 // let cont join(v0, v1, ...) = [[successor]] in 1755 // let cont join(v0, v1, ...) = [[successor]] in
1741 // let mutable m0 = x0 in 1756 // let mutable m0 = x0 in
1742 // let mutable m1 = x1 in 1757 // let mutable m1 = x1 in
1743 // ... 1758 // ...
(...skipping 12 matching lines...) Expand all
1756 // 1771 //
1757 // In other words, both the try and catch block are in the scope of the 1772 // In other words, both the try and catch block are in the scope of the
1758 // join-point continuation, and they are both in the scope of a sequence 1773 // join-point continuation, and they are both in the scope of a sequence
1759 // of mutable bindings for the variables assigned in the try. The join- 1774 // of mutable bindings for the variables assigned in the try. The join-
1760 // point continuation is not in the scope of these mutable bindings. 1775 // point continuation is not in the scope of these mutable bindings.
1761 // The tryBlock is in the scope of a binding for the catch handler. Each 1776 // The tryBlock is in the scope of a binding for the catch handler. Each
1762 // instruction (specifically, each call) in the tryBlock is in the dynamic 1777 // instruction (specifically, each call) in the tryBlock is in the dynamic
1763 // scope of the handler. The mutable bindings are dereferenced at the end 1778 // scope of the handler. The mutable bindings are dereferenced at the end
1764 // of the try block and at the beginning of the catch block, so the 1779 // of the try block and at the beginning of the catch block, so the
1765 // variables are unboxed in the catch block and at the join point. 1780 // variables are unboxed in the catch block and at the join point.
1766 JumpCollector join = new ForwardJumpCollector(environment); 1781 if (catchClauseInfos.isNotEmpty) {
1767 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); 1782 JumpCollector join = new ForwardJumpCollector(environment);
Kevin Millikin (Google) 2015/06/22 15:36:42 This is the code for try/catch. It is unchanged e
1783 IrBuilder tryCatchBuilder = makeDelimitedBuilder();
1768 1784
1769 // Variables treated as mutable in a try are not mutable outside of it. 1785 // Variables treated as mutable in a try are not mutable outside of it.
1770 // Work with a copy of the outer builder's mutable variables. 1786 // Work with a copy of the outer builder's mutable variables.
1771 tryCatchBuilder.mutableVariables = 1787 tryCatchBuilder.mutableVariables =
1772 new Map<Local, ir.MutableVariable>.from(mutableVariables); 1788 new Map<Local, ir.MutableVariable>.from(mutableVariables);
1773 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) { 1789 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1774 assert(!tryCatchBuilder.isInMutableVariable(variable)); 1790 assert(!tryCatchBuilder.isInMutableVariable(variable));
1775 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable); 1791 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable);
1776 tryCatchBuilder.makeMutableVariable(variable); 1792 tryCatchBuilder.makeMutableVariable(variable);
1777 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); 1793 tryCatchBuilder.declareLocalVariable(variable, initialValue: value);
1794 }
1795
1796 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
1797
1798 void interceptJump(JumpCollector collector) {
1799 collector.enterTry(tryStatementInfo.boxedOnEntry);
1800 }
1801 void restoreJump(JumpCollector collector) {
1802 collector.leaveTry();
1803 }
1804 tryBuilder.state.breakCollectors.forEach(interceptJump);
1805 tryBuilder.state.continueCollectors.forEach(interceptJump);
1806 buildTryBlock(tryBuilder);
1807 if (tryBuilder.isOpen) {
1808 interceptJump(join);
1809 tryBuilder.jumpTo(join);
1810 restoreJump(join);
1811 }
1812 tryBuilder.state.breakCollectors.forEach(restoreJump);
1813 tryBuilder.state.continueCollectors.forEach(restoreJump);
1814
1815 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
1816 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1817 assert(catchBuilder.isInMutableVariable(variable));
1818 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable);
1819 // After this point, the variables that were boxed on entry to the try
1820 // are no longer treated as mutable.
1821 catchBuilder.removeMutableVariable(variable);
1822 catchBuilder.environment.update(variable, value);
1823 }
1824
1825 // Handlers are always translated as having both exception and stack trace
1826 // parameters. Multiple clauses do not have to use the same names for
1827 // them. Choose the first of each as the name hint for the respective
1828 // handler parameter.
1829 ir.Parameter exceptionParameter =
1830 new ir.Parameter(catchClauseInfos.first.exceptionVariable);
1831 LocalVariableElement traceVariable;
1832 CatchClauseInfo catchAll;
1833 for (int i = 0; i < catchClauseInfos.length; ++i) {
1834 CatchClauseInfo info = catchClauseInfos[i];
1835 if (info.type == null) {
1836 catchAll = info;
1837 catchClauseInfos.length = i;
1838 break;
1839 }
1840 if (traceVariable == null) {
1841 traceVariable = info.stackTraceVariable;
1842 }
1843 }
1844 ir.Parameter traceParameter = new ir.Parameter(traceVariable);
1845 // Expand multiple catch clauses into an explicit if/then/else. Iterate
1846 // them in reverse so the current block becomes the next else block.
1847 ir.Expression catchBody;
1848 if (catchAll == null) {
1849 catchBody = new ir.Rethrow();
1850 } else {
1851 IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
1852 clauseBuilder.declareLocalVariable(catchAll.exceptionVariable,
1853 initialValue: exceptionParameter);
1854 if (catchAll.stackTraceVariable != null) {
1855 clauseBuilder.declareLocalVariable(catchAll.stackTraceVariable,
1856 initialValue: traceParameter);
1857 }
1858 catchAll.buildCatchBlock(clauseBuilder);
1859 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1860 catchBody = clauseBuilder._root;
1861 }
1862 for (CatchClauseInfo clause in catchClauseInfos.reversed) {
1863 IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
1864 clauseBuilder.declareLocalVariable(clause.exceptionVariable,
1865 initialValue: exceptionParameter);
1866 if (clause.stackTraceVariable != null) {
1867 clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
1868 initialValue: traceParameter);
1869 }
1870 clause.buildCatchBlock(clauseBuilder);
1871 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1872 ir.Continuation thenContinuation = new ir.Continuation([]);
1873 thenContinuation.body = clauseBuilder._root;
1874 ir.Continuation elseContinuation = new ir.Continuation([]);
1875 elseContinuation.body = catchBody;
1876
1877 // Build the type test guarding this clause. We can share the
1878 // environment with the nested builder because this part cannot mutate
1879 // it.
1880 IrBuilder checkBuilder = catchBuilder.makeDelimitedBuilder(environment);
1881 ir.Primitive typeMatches =
1882 checkBuilder.buildTypeOperator(exceptionParameter,
1883 clause.type,
1884 isTypeTest: true);
1885 checkBuilder.add(new ir.LetCont.many([thenContinuation,
1886 elseContinuation],
1887 new ir.Branch(new ir.IsTrue(typeMatches),
1888 thenContinuation,
1889 elseContinuation)));
1890 catchBody = checkBuilder._root;
1891 }
1892
1893 List<ir.Parameter> catchParameters =
1894 <ir.Parameter>[exceptionParameter, traceParameter];
1895 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1896 catchBuilder.add(catchBody);
1897 catchContinuation.body = catchBuilder._root;
1898
1899 tryCatchBuilder.add(
1900 new ir.LetHandler(catchContinuation, tryBuilder._root));
1901 add(new ir.LetCont(join.continuation, tryCatchBuilder._root));
1902 environment = join.environment;
1903 } else {
1904 // Try/finally.
Kevin Millikin (Google) 2015/06/22 15:36:42 This is the code for try/finally. There is a lot
1905 JumpCollector join = new ForwardJumpCollector(environment);
1906 IrBuilder tryFinallyBuilder = makeDelimitedBuilder();
1907
1908 tryFinallyBuilder.mutableVariables =
1909 new Map<Local, ir.MutableVariable>.from(mutableVariables);
1910 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1911 assert(!tryFinallyBuilder.isInMutableVariable(variable));
1912 ir.Primitive value = tryFinallyBuilder.buildLocalVariableGet(variable);
1913 tryFinallyBuilder.makeMutableVariable(variable);
1914 tryFinallyBuilder.declareLocalVariable(variable, initialValue: value);
1915 }
1916
1917 IrBuilder tryBuilder = tryFinallyBuilder.makeDelimitedBuilder();
1918
1919 void interceptJump(JumpCollector collector) {
1920 collector.enterTry(tryStatementInfo.boxedOnEntry, buildFinallyBlock);
1921 }
1922 void restoreJump(JumpCollector collector) {
1923 collector.leaveTry();
1924 }
1925 tryBuilder.state.breakCollectors.forEach(interceptJump);
1926 tryBuilder.state.continueCollectors.forEach(interceptJump);
1927 tryBuilder.state.finallyBlocks.add(buildFinallyBlock);
1928 buildTryBlock(tryBuilder);
1929 if (tryBuilder.isOpen) {
1930 // To cover control falling off the end of the try block, the finally
1931 // code is translated at the join point. This ensures that it is
1932 // correctly outside the scope of the catch handler.
1933 join.enterTry(tryStatementInfo.boxedOnEntry);
1934 tryBuilder.jumpTo(join);
1935 join.leaveTry();
1936 }
1937 tryBuilder.state.breakCollectors.forEach(restoreJump);
1938 tryBuilder.state.continueCollectors.forEach(restoreJump);
1939 tryBuilder.state.finallyBlocks.removeLast();
1940
1941 IrBuilder catchBuilder = tryFinallyBuilder.makeDelimitedBuilder();
1942 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1943 assert(catchBuilder.isInMutableVariable(variable));
1944 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable);
1945 catchBuilder.removeMutableVariable(variable);
1946 catchBuilder.environment.update(variable, value);
1947 }
1948
1949 buildFinallyBlock(catchBuilder);
1950 if (catchBuilder.isOpen) {
1951 catchBuilder.add(new ir.Rethrow());
1952 catchBuilder._current = null;
1953 }
1954 List<ir.Parameter> catchParameters =
1955 <ir.Parameter>[new ir.Parameter(null), new ir.Parameter(null)];
1956 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1957 catchContinuation.body = catchBuilder._root;
1958 tryFinallyBuilder.add(
1959 new ir.LetHandler(catchContinuation, tryBuilder._root));
1960 add(new ir.LetCont(join.continuation, tryFinallyBuilder._root));
1961 environment = join.environment;
1962 buildFinallyBlock(this);
1778 } 1963 }
1779
1780 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
1781
1782 void interceptJumps(JumpCollector collector) {
1783 collector.enterTry(tryStatementInfo.boxedOnEntry);
1784 }
1785 void restoreJumps(JumpCollector collector) {
1786 collector.leaveTry();
1787 }
1788 tryBuilder.state.breakCollectors.forEach(interceptJumps);
1789 tryBuilder.state.continueCollectors.forEach(interceptJumps);
1790 buildTryBlock(tryBuilder);
1791 if (tryBuilder.isOpen) {
1792 interceptJumps(join);
1793 tryBuilder.jumpTo(join);
1794 restoreJumps(join);
1795 }
1796 tryBuilder.state.breakCollectors.forEach(restoreJumps);
1797 tryBuilder.state.continueCollectors.forEach(restoreJumps);
1798
1799 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
1800 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1801 assert(catchBuilder.isInMutableVariable(variable));
1802 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable);
1803 // After this point, the variables that were boxed on entry to the try
1804 // are no longer treated as mutable.
1805 catchBuilder.removeMutableVariable(variable);
1806 catchBuilder.environment.update(variable, value);
1807 }
1808
1809 // Handlers are always translated as having both exception and stack trace
1810 // parameters. Multiple clauses do not have to use the same names for
1811 // them. Choose the first of each as the name hint for the respective
1812 // handler parameter.
1813 ir.Parameter exceptionParameter =
1814 new ir.Parameter(catchClauseInfos.first.exceptionVariable);
1815 LocalVariableElement traceVariable;
1816 CatchClauseInfo catchAll;
1817 for (int i = 0; i < catchClauseInfos.length; ++i) {
1818 CatchClauseInfo info = catchClauseInfos[i];
1819 if (info.type == null) {
1820 catchAll = info;
1821 catchClauseInfos.length = i;
1822 break;
1823 }
1824 if (traceVariable == null) {
1825 traceVariable = info.stackTraceVariable;
1826 }
1827 }
1828 ir.Parameter traceParameter = new ir.Parameter(traceVariable);
1829 // Expand multiple catch clauses into an explicit if/then/else. Iterate
1830 // them in reverse so the current block becomes the next else block.
1831 ir.Expression catchBody;
1832 if (catchAll == null) {
1833 catchBody = new ir.Rethrow();
1834 } else {
1835 IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
1836 clauseBuilder.declareLocalVariable(catchAll.exceptionVariable,
1837 initialValue: exceptionParameter);
1838 if (catchAll.stackTraceVariable != null) {
1839 clauseBuilder.declareLocalVariable(catchAll.stackTraceVariable,
1840 initialValue: traceParameter);
1841 }
1842 catchAll.buildCatchBlock(clauseBuilder);
1843 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1844 catchBody = clauseBuilder._root;
1845 }
1846 for (CatchClauseInfo clause in catchClauseInfos.reversed) {
1847 IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
1848 clauseBuilder.declareLocalVariable(clause.exceptionVariable,
1849 initialValue: exceptionParameter);
1850 if (clause.stackTraceVariable != null) {
1851 clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
1852 initialValue: traceParameter);
1853 }
1854 clause.buildCatchBlock(clauseBuilder);
1855 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1856 ir.Continuation thenContinuation = new ir.Continuation([]);
1857 thenContinuation.body = clauseBuilder._root;
1858 ir.Continuation elseContinuation = new ir.Continuation([]);
1859 elseContinuation.body = catchBody;
1860
1861 // Build the type test guarding this clause. We can share the environment
1862 // with the nested builder because this part cannot mutate it.
1863 IrBuilder checkBuilder = catchBuilder.makeDelimitedBuilder(environment);
1864 ir.Primitive typeMatches =
1865 checkBuilder.buildTypeOperator(exceptionParameter,
1866 clause.type,
1867 isTypeTest: true);
1868 checkBuilder.add(new ir.LetCont.many([thenContinuation, elseContinuation],
1869 new ir.Branch(new ir.IsTrue(typeMatches),
1870 thenContinuation,
1871 elseContinuation)));
1872 catchBody = checkBuilder._root;
1873 }
1874
1875 List<ir.Parameter> catchParameters =
1876 <ir.Parameter>[exceptionParameter, traceParameter];
1877 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1878 catchBuilder.add(catchBody);
1879 catchContinuation.body = catchBuilder._root;
1880
1881 tryCatchBuilder.add(
1882 new ir.LetHandler(catchContinuation, tryBuilder._root));
1883 add(new ir.LetCont(join.continuation, tryCatchBuilder._root));
1884 environment = join.environment;
1885 } 1964 }
1886 1965
1887 /// Create a return statement `return value;` or `return;` if [value] is 1966 /// Create a return statement `return value;` or `return;` if [value] is
1888 /// null. 1967 /// null.
1889 void buildReturn([ir.Primitive value]) { 1968 void buildReturn([ir.Primitive value]) {
1890 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 1969 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
1891 // where (C', x) = Build(e, C) 1970 // where (C', x) = Build(e, C)
1892 // 1971 //
1893 // Return without a subexpression is translated as if it were return null. 1972 // Return without a subexpression is translated as if it were return null.
1894 assert(isOpen); 1973 assert(isOpen);
1895 if (value == null) { 1974 if (value == null) {
1896 value = buildNullConstant(); 1975 value = buildNullConstant();
1897 } 1976 }
1898 add(new ir.InvokeContinuation(state.returnContinuation, [value])); 1977 for (SubbuildFunction buildFinallyBlock in state.finallyBlocks.reversed) {
1899 _current = null; 1978 buildFinallyBlock(this);
1979 if (!isOpen) break;
1980 }
1981 if (isOpen) {
1982 add(new ir.InvokeContinuation(state.returnContinuation, [value]));
1983 _current = null;
1984 }
1900 } 1985 }
1901 1986
1902 /// Create a blocks of [statements] by applying [build] to all reachable 1987 /// Create a blocks of [statements] by applying [build] to all reachable
1903 /// statements. The first statement is assumed to be reachable. 1988 /// statements. The first statement is assumed to be reachable.
1904 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses 1989 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses
1905 // `List` instead of `Link`. 1990 // `List` instead of `Link`.
1906 void buildBlock(var statements, BuildFunction build) { 1991 void buildBlock(var statements, BuildFunction build) {
1907 // Build(Block(stamements), C) = C' 1992 // Build(Block(stamements), C) = C'
1908 // where C' = statements.fold(Build, C) 1993 // where C' = statements.fold(Build, C)
1909 assert(isOpen); 1994 assert(isOpen);
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after
2629 this.buildCatchBlock}); 2714 this.buildCatchBlock});
2630 } 2715 }
2631 2716
2632 class SwitchCaseInfo { 2717 class SwitchCaseInfo {
2633 final List<ir.Primitive> constants = <ir.Primitive>[]; 2718 final List<ir.Primitive> constants = <ir.Primitive>[];
2634 final SubbuildFunction buildBody; 2719 final SubbuildFunction buildBody;
2635 2720
2636 SwitchCaseInfo(this.buildBody); 2721 SwitchCaseInfo(this.buildBody);
2637 2722
2638 void addConstant(ir.Primitive constant) => constants.add(constant); 2723 void addConstant(ir.Primitive constant) => constants.add(constant);
2639 } 2724 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698