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

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: Merge, rebase test expectations. 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 index2value = other.index2variable.map((Local local) { 61 index2value = other.index2variable.map((Local local) {
62 return new ir.Parameter(local); 62 return new ir.Parameter(local);
63 }).toList(); 63 }).toList();
64 64
65 get length => index2variable.length; 65 get length => index2variable.length;
66 66
67 ir.Primitive operator [](int index) => index2value[index]; 67 ir.Primitive operator [](int index) => index2value[index];
68 68
69 void extend(Local element, ir.Primitive value) { 69 void extend(Local element, ir.Primitive value) {
70 // Assert that the name is not already in the environment. `null` is used 70 // Assert that the name is not already in the environment. `null` is used
71 // as the name of anonymous variables. Because the variable2index map is 71 // as the name of anonymous variables.
72 // shared, `null` can already occur. This is safe because such variables 72 assert(!variable2index.containsKey(element));
73 // are not looked up by name. 73 if (element != null) variable2index[element] = index2variable.length;
74 //
75 // TODO(kmillikin): This is still kind of fishy. Refactor to not share
76 // name maps or else garbage collect unneeded names.
77 assert(element == null || !variable2index.containsKey(element));
78 variable2index[element] = index2variable.length;
79 index2variable.add(element); 74 index2variable.add(element);
80 index2value.add(value); 75 index2value.add(value);
81 } 76 }
82 77
83 void discard(int count) { 78 /// Drop [count] values from the environment.
79 ///
80 /// Return the previous last value in the environment for convenience.
81 ir.Primitive discard(int count) {
82 assert(count > 0);
84 assert(count <= index2variable.length); 83 assert(count <= index2variable.length);
84 ir.Primitive value = index2value.last;
85 // The map from variables to their index are shared, so we cannot remove 85 // The map from variables to their index are shared, so we cannot remove
86 // the mapping in `variable2index`. 86 // the mapping in `variable2index`.
87 index2variable.length -= count; 87 index2variable.length -= count;
88 index2value.length -= count; 88 index2value.length -= count;
89 return value;
89 } 90 }
90 91
91 ir.Primitive lookup(Local element) { 92 ir.Primitive lookup(Local element) {
92 assert(invariant(element, variable2index.containsKey(element), 93 assert(invariant(element, variable2index.containsKey(element),
93 message: "Unknown variable: $element.")); 94 message: "Unknown variable: $element."));
94 return index2value[variable2index[element]]; 95 return index2value[variable2index[element]];
95 } 96 }
96 97
97 void update(Local element, ir.Primitive value) { 98 void update(Local element, ir.Primitive value) {
98 index2value[variable2index[element]] = value; 99 index2value[variable2index[element]] = value;
99 } 100 }
100 101
101 /// Verify that the variable2index and index2variable maps agree up to the 102 /// Verify that the variable2index and index2variable maps agree up to the
102 /// index [length] exclusive. 103 /// index [length] exclusive.
103 bool sameDomain(int length, Environment other) { 104 bool sameDomain(int length, Environment other) {
104 assert(this.length >= length); 105 assert(this.length >= length);
105 assert(other.length >= length); 106 assert(other.length >= length);
106 for (int i = 0; i < length; ++i) { 107 for (int i = 0; i < length; ++i) {
107 // An index maps to the same variable in both environments. 108 // An index maps to the same variable in both environments.
108 Local variable = index2variable[i]; 109 Local variable = index2variable[i];
109 if (variable != other.index2variable[i]) return false; 110 if (variable != other.index2variable[i]) return false;
110 111
111 // The variable maps to the same index in both environments. 112 // A named variable maps to the same index in both environments.
112 int index = variable2index[variable]; 113 if (variable != null) {
113 if (index == null || index != other.variable2index[variable]) { 114 int index = variable2index[variable];
114 return false; 115 if (index == null || index != other.variable2index[variable]) {
116 return false;
117 }
115 } 118 }
116 } 119 }
117 return true; 120 return true;
118 } 121 }
119 122
120 bool contains(Local local) => variable2index.containsKey(local); 123 bool contains(Local local) => variable2index.containsKey(local);
121 } 124 }
122 125
123 /// The abstract base class of objects that emit jumps to a continuation and 126 /// The abstract base class of objects that emit jumps to a continuation and
124 /// give a handle to the continuation and its environment. 127 /// give a handle to the continuation and its environment.
125 abstract class JumpCollector { 128 abstract class JumpCollector {
126 final JumpTarget target; 129 final JumpTarget target;
127 130
128 ir.Continuation _continuation = null; 131 ir.Continuation _continuation = null;
129 final Environment _continuationEnvironment; 132 final Environment _continuationEnvironment;
130 133
131 final List<Iterable<LocalVariableElement>> _boxedTryVariables = 134 final List<Iterable<LocalVariableElement>> _boxedTryVariables =
132 <Iterable<LocalVariableElement>>[]; 135 <Iterable<LocalVariableElement>>[];
133 136
134 JumpCollector(this._continuationEnvironment, this.target); 137 /// Construct a collector for a given environment and optionally a target.
138 ///
139 /// The environment is the one in effect at the point where the jump's
140 /// continuation will be bound. Continuations can take an extra argument
141 /// (see [addJump]).
142 JumpCollector(this._continuationEnvironment, this.target,
143 bool hasExtraArgument) {
144 if (hasExtraArgument) _continuationEnvironment.extend(null, null);
145 }
135 146
136 /// True if the collector has not recorded any jumps to its continuation. 147 /// True if the collector has not recorded any jumps to its continuation.
137 bool get isEmpty; 148 bool get isEmpty;
138 149
139 /// The continuation encapsulated by this collector. 150 /// The continuation encapsulated by this collector.
140 ir.Continuation get continuation; 151 ir.Continuation get continuation;
141 152
142 /// The compile-time environment to be used for translating code in the body 153 /// The compile-time environment to be used for translating code in the body
143 /// of the continuation. 154 /// of the continuation.
144 Environment get environment; 155 Environment get environment;
145 156
146 /// Emit a jump to the continuation for a given [IrBuilder]. 157 /// Emit a jump to the continuation for a given [IrBuilder].
147 void addJump(IrBuilder builder); 158 ///
159 /// Jumps can take a single extra argument. This is used to pass return
160 /// values to finally blocks for returns inside try/finally and to pass
161 /// values of expressions that have internal control flow to their join-point
162 /// continuations.
163 void addJump(IrBuilder builder, [ir.Primitive value]);
148 164
149 /// Add a set of variables that were boxed on entry to a try block. 165 /// Add a set of variables that were boxed on entry to a try block.
150 /// 166 ///
151 /// All jumps from a try block to targets outside have to unbox the 167 /// All jumps from a try block to targets outside have to unbox the
152 /// variables that were boxed on entry before invoking the target 168 /// variables that were boxed on entry before invoking the target
153 /// continuation. Call this function before translating a try block and 169 /// continuation. Call this function before translating a try block and
154 /// call [leaveTry] after translating it. 170 /// call [leaveTry] after translating it.
155 void enterTry(Iterable<LocalVariableElement> boxedOnEntry) { 171 void enterTry(Iterable<LocalVariableElement> boxedOnEntry) {
156 // The boxed variables are maintained as a stack to make leaving easy. 172 // The boxed variables are maintained as a stack to make leaving easy.
157 _boxedTryVariables.add(boxedOnEntry); 173 _boxedTryVariables.add(boxedOnEntry);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 class ForwardJumpCollector extends JumpCollector { 215 class ForwardJumpCollector extends JumpCollector {
200 final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[]; 216 final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[];
201 final List<Environment> _invocationEnvironments = <Environment>[]; 217 final List<Environment> _invocationEnvironments = <Environment>[];
202 218
203 /// Construct a collector with a given base environment. 219 /// Construct a collector with a given base environment.
204 /// 220 ///
205 /// The base environment is the one in scope at the site that the 221 /// The base environment is the one in scope at the site that the
206 /// continuation represented by this collector will be bound. The 222 /// continuation represented by this collector will be bound. The
207 /// environment is copied by the collector. Subsequent mutation of the 223 /// environment is copied by the collector. Subsequent mutation of the
208 /// original environment will not affect the collector. 224 /// original environment will not affect the collector.
209 ForwardJumpCollector(Environment environment, {JumpTarget target: null}) 225 ForwardJumpCollector(Environment environment,
210 : super(new Environment.from(environment), target); 226 {JumpTarget target, bool hasExtraArgument: false})
227 : super(new Environment.from(environment), target, hasExtraArgument);
211 228
212 bool get isEmpty => _invocations.isEmpty; 229 bool get isEmpty => _invocations.isEmpty;
213 230
214 ir.Continuation get continuation { 231 ir.Continuation get continuation {
215 if (_continuation == null) _setContinuation(); 232 if (_continuation == null) _setContinuation();
216 return _continuation; 233 return _continuation;
217 } 234 }
218 235
219 Environment get environment { 236 Environment get environment {
220 if (_continuation == null) _setContinuation(); 237 if (_continuation == null) _setContinuation();
221 return _continuationEnvironment; 238 return _continuationEnvironment;
222 } 239 }
223 240
224 void addJump(IrBuilder builder) { 241 void addJump(IrBuilder builder, [ir.Primitive value]) {
225 assert(_continuation == null); 242 assert(_continuation == null);
226 _buildTryExit(builder); 243 _buildTryExit(builder);
227 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized(); 244 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized();
228 builder.add(invoke); 245 builder.add(invoke);
229 _invocations.add(invoke); 246 _invocations.add(invoke);
247 // Truncate the environment at the invocation site so it only includes
248 // values that will be continuation arguments. If an extra value is passed
249 // it will already be included in the continuation environment, but it is
250 // not present in the invocation environment.
251 int delta = builder.environment.length - _continuationEnvironment.length;
252 if (value != null) ++delta;
253 if (delta > 0) builder.environment.discard(delta);
254 if (value != null) builder.environment.extend(null, value);
230 _invocationEnvironments.add(builder.environment); 255 _invocationEnvironments.add(builder.environment);
231 builder._current = null; 256 builder._current = null;
232 // TODO(kmillikin): Can we set builder.environment to null to make it 257 // TODO(kmillikin): Can we set builder.environment to null to make it
233 // less likely to mutate it? 258 // less likely to mutate it?
234 } 259 }
235 260
236 void _setContinuation() { 261 void _setContinuation() {
237 assert(_continuation == null); 262 assert(_continuation == null);
238 // We have seen all invocations of this continuation, and recorded the 263 // We have seen all invocations of this continuation, and recorded the
239 // environment in effect at each invocation site. 264 // environment in effect at each invocation site.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 /// parameter for each variable in scope at the entry to the continuation, 326 /// parameter for each variable in scope at the entry to the continuation,
302 /// before emitting any jump to the continuation. When a jump is added, it 327 /// before emitting any jump to the continuation. When a jump is added, it
303 /// is given an argument for each continuation parameter. 328 /// is given an argument for each continuation parameter.
304 class BackwardJumpCollector extends JumpCollector { 329 class BackwardJumpCollector extends JumpCollector {
305 /// Construct a collector with a given base environment. 330 /// Construct a collector with a given base environment.
306 /// 331 ///
307 /// The base environment is the one in scope at the site that the 332 /// The base environment is the one in scope at the site that the
308 /// continuation represented by this collector will be bound. The 333 /// continuation represented by this collector will be bound. The
309 /// translation of the continuation body will use an environment with the 334 /// translation of the continuation body will use an environment with the
310 /// same shape, but with fresh continuation parameters for each variable. 335 /// same shape, but with fresh continuation parameters for each variable.
311 BackwardJumpCollector(Environment environment, {JumpTarget target: null}) 336 BackwardJumpCollector(Environment environment,
312 : super(new Environment.fresh(environment), target) { 337 {JumpTarget target, bool hasExtraArgument: false})
338 : super(new Environment.fresh(environment), target, hasExtraArgument) {
313 List<ir.Parameter> parameters = 339 List<ir.Parameter> parameters =
314 new List<ir.Parameter>.from(_continuationEnvironment.index2value); 340 new List<ir.Parameter>.from(_continuationEnvironment.index2value);
315 _continuation = new ir.Continuation(parameters, isRecursive: true); 341 _continuation = new ir.Continuation(parameters, isRecursive: true);
316 } 342 }
317 343
318 bool isEmpty = true; 344 bool isEmpty = true;
319 345
320 ir.Continuation get continuation => _continuation; 346 ir.Continuation get continuation => _continuation;
321 Environment get environment => _continuationEnvironment; 347 Environment get environment => _continuationEnvironment;
322 348
323 void addJump(IrBuilder builder) { 349 void addJump(IrBuilder builder, [ir.Primitive value]) {
324 assert(_continuation.parameters.length <= builder.environment.length); 350 assert(_continuation.parameters.length <= builder.environment.length);
325 isEmpty = false; 351 isEmpty = false;
326 _buildTryExit(builder); 352 _buildTryExit(builder);
353 // Truncate the environment at the invocation site so it only includes
354 // values that will be continuation arguments. If an extra value is passed
355 // it will already be included in the continuation environment, but it is
356 // not present in the invocation environment.
357 int delta = builder.environment.length - _continuationEnvironment.length;
358 if (value != null) ++delta;
359 if (delta > 0) builder.environment.discard(delta);
360 if (value != null) builder.environment.extend(null, value);
327 builder.add(new ir.InvokeContinuation(_continuation, 361 builder.add(new ir.InvokeContinuation(_continuation,
328 builder.environment.index2value.take(_continuation.parameters.length) 362 builder.environment.index2value,
329 .toList(),
330 isRecursive: true)); 363 isRecursive: true));
331 builder._current = null; 364 builder._current = null;
332 } 365 }
333 } 366 }
334 367
335 /// Function for building a node in the context of the current builder. 368 /// Function for building a node in the context of the current builder.
336 typedef ir.Node BuildFunction(node); 369 typedef ir.Node BuildFunction(node);
337 370
338 /// Function for building nodes in the context of the provided [builder]. 371 /// Function for building nodes in the context of the provided [builder].
339 typedef ir.Node SubbuildFunction(IrBuilder builder); 372 typedef ir.Node SubbuildFunction(IrBuilder builder);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 } 420 }
388 } 421 }
389 422
390 /// Shared state between delimited IrBuilders within the same function. 423 /// Shared state between delimited IrBuilders within the same function.
391 class IrBuilderSharedState { 424 class IrBuilderSharedState {
392 final BackendConstantEnvironment constants; 425 final BackendConstantEnvironment constants;
393 426
394 ConstantSystem get constantSystem => constants.constantSystem; 427 ConstantSystem get constantSystem => constants.constantSystem;
395 428
396 /// A stack of collectors for breaks. 429 /// A stack of collectors for breaks.
397 final List<JumpCollector> breakCollectors = <JumpCollector>[]; 430 List<JumpCollector> breakCollectors = <JumpCollector>[];
398 431
399 /// A stack of collectors for continues. 432 /// A stack of collectors for continues.
400 final List<JumpCollector> continueCollectors = <JumpCollector>[]; 433 List<JumpCollector> continueCollectors = <JumpCollector>[];
401 434
402 final ExecutableElement currentElement; 435 final ExecutableElement currentElement;
403 436
404 final ir.Continuation returnContinuation = new ir.Continuation.retrn(); 437 final ir.Continuation returnContinuation = new ir.Continuation.retrn();
438
439 /// The target of a return from the function.
440 ///
441 /// A null value indicates that the target is the function's return
442 /// continuation. Otherwise, when inside the try block of try/finally
443 /// a return is intercepted to give a place to generate the finally code.
444 JumpCollector returnCollector = null;
445
405 ir.Parameter _thisParameter; 446 ir.Parameter _thisParameter;
406 ir.Parameter enclosingMethodThisParameter; 447 ir.Parameter enclosingMethodThisParameter;
407 448
408 final List<ir.Parameter> functionParameters = <ir.Parameter>[]; 449 final List<ir.Parameter> functionParameters = <ir.Parameter>[];
409 450
410 IrBuilderSharedState(this.constants, this.currentElement); 451 IrBuilderSharedState(this.constants, this.currentElement);
411 452
412 ir.Parameter get thisParameter => _thisParameter; 453 ir.Parameter get thisParameter => _thisParameter;
413 void set thisParameter(ir.Parameter value) { 454 void set thisParameter(ir.Parameter value) {
414 assert(_thisParameter == null); 455 assert(_thisParameter == null);
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 IrBuilder elseBuilder = makeDelimitedBuilder(); 784 IrBuilder elseBuilder = makeDelimitedBuilder();
744 ir.Primitive thenValue = buildThenExpression(thenBuilder); 785 ir.Primitive thenValue = buildThenExpression(thenBuilder);
745 ir.Primitive elseValue = buildElseExpression(elseBuilder); 786 ir.Primitive elseValue = buildElseExpression(elseBuilder);
746 787
747 // Treat the values of the subexpressions as named values in the 788 // Treat the values of the subexpressions as named values in the
748 // environment, so they will be treated as arguments to the join-point 789 // environment, so they will be treated as arguments to the join-point
749 // continuation. We know the environments are the right size because 790 // continuation. We know the environments are the right size because
750 // expressions cannot introduce variable bindings. 791 // expressions cannot introduce variable bindings.
751 assert(environment.length == thenBuilder.environment.length); 792 assert(environment.length == thenBuilder.environment.length);
752 assert(environment.length == elseBuilder.environment.length); 793 assert(environment.length == elseBuilder.environment.length);
753 // Extend the join-point environment with a placeholder for the value of 794 JumpCollector join =
754 // the expression. Optimistically assume that the value is the value of 795 new ForwardJumpCollector(environment, hasExtraArgument: true);
755 // the first subexpression. This value might noe even be in scope at the 796 thenBuilder.jumpTo(join, thenValue);
756 // join-point because it's bound in the first subexpression. However, if 797 elseBuilder.jumpTo(join, elseValue);
757 // that is the case, it will necessarily differ from the value of the
758 // other subexpression and cause the introduction of a join-point
759 // continuation parameter. If the two values do happen to be the same,
760 // this will avoid inserting a useless continuation parameter.
761 environment.extend(null, thenValue);
762 thenBuilder.environment.extend(null, thenValue);
763 elseBuilder.environment.extend(null, elseValue);
764 JumpCollector join = new ForwardJumpCollector(environment);
765 thenBuilder.jumpTo(join);
766 elseBuilder.jumpTo(join);
767 798
768 // Build the term 799 // Build the term
769 // let cont join(x, ..., result) = [] in 800 // let cont join(x, ..., result) = [] in
770 // let cont then() = [[thenPart]]; join(v, ...) 801 // let cont then() = [[thenPart]]; join(v, ...)
771 // and else() = [[elsePart]]; join(v, ...) 802 // and else() = [[elsePart]]; join(v, ...)
772 // in 803 // in
773 // if condition (then, else) 804 // if condition (then, else)
774 ir.Continuation thenContinuation = new ir.Continuation([]); 805 ir.Continuation thenContinuation = new ir.Continuation([]);
775 ir.Continuation elseContinuation = new ir.Continuation([]); 806 ir.Continuation elseContinuation = new ir.Continuation([]);
776 thenContinuation.body = thenBuilder._root; 807 thenContinuation.body = thenBuilder._root;
777 elseContinuation.body = elseBuilder._root; 808 elseContinuation.body = elseBuilder._root;
778 add(new ir.LetCont(join.continuation, 809 add(new ir.LetCont(join.continuation,
779 new ir.LetCont.many(<ir.Continuation>[thenContinuation, 810 new ir.LetCont.many(<ir.Continuation>[thenContinuation,
780 elseContinuation], 811 elseContinuation],
781 new ir.Branch(new ir.IsTrue(condition), 812 new ir.Branch(new ir.IsTrue(condition),
782 thenContinuation, 813 thenContinuation,
783 elseContinuation)))); 814 elseContinuation))));
784 environment = join.environment; 815 environment = join.environment;
785 environment.discard(1); 816 return environment.discard(1);
786 return (thenValue == elseValue)
787 ? thenValue
788 : join.continuation.parameters.last;
789 } 817 }
790 818
791 /** 819 /**
792 * Add an explicit `return null` for functions that don't have a return 820 * Add an explicit `return null` for functions that don't have a return
793 * statement on each branch. This includes functions with an empty body, 821 * statement on each branch. This includes functions with an empty body,
794 * such as `foo(){ }`. 822 * such as `foo(){ }`.
795 */ 823 */
796 void _ensureReturn() { 824 void _ensureReturn() {
797 if (!isOpen) return; 825 if (!isOpen) return;
798 ir.Constant constant = buildNullConstant(); 826 ir.Constant constant = buildNullConstant();
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 if (elseBuilder._root != null) _current = elseBuilder._current; 1190 if (elseBuilder._root != null) _current = elseBuilder._current;
1163 environment = elseBuilder.environment; 1191 environment = elseBuilder.environment;
1164 } else { 1192 } else {
1165 _current = null; 1193 _current = null;
1166 } 1194 }
1167 } else { 1195 } else {
1168 environment = join.environment; 1196 environment = join.environment;
1169 } 1197 }
1170 } 1198 }
1171 1199
1172 void jumpTo(JumpCollector collector) { 1200 void jumpTo(JumpCollector collector, [ir.Primitive value]) {
1173 collector.addJump(this); 1201 collector.addJump(this, value);
1174 } 1202 }
1175 1203
1176 void addRecursiveContinuation(BackwardJumpCollector collector) { 1204 void addRecursiveContinuation(BackwardJumpCollector collector) {
1177 assert(environment.length == collector.environment.length); 1205 assert(environment.length == collector.environment.length);
1178 add(new ir.LetCont(collector.continuation, 1206 add(new ir.LetCont(collector.continuation,
1179 new ir.InvokeContinuation(collector.continuation, 1207 new ir.InvokeContinuation(collector.continuation,
1180 environment.index2value))); 1208 environment.index2value)));
1181 environment = collector.environment; 1209 environment = collector.environment;
1182 } 1210 }
1183 1211
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 /// 1736 ///
1709 /// [tryInfo] provides information on local variables declared and boxed 1737 /// [tryInfo] provides information on local variables declared and boxed
1710 /// within this try statement. 1738 /// within this try statement.
1711 /// [buildTryBlock] builds the try block. 1739 /// [buildTryBlock] builds the try block.
1712 /// [catchClauseInfos] provides access to the catch type, exception variable, 1740 /// [catchClauseInfos] provides access to the catch type, exception variable,
1713 /// and stack trace variable, and a function for building the catch block. 1741 /// and stack trace variable, and a function for building the catch block.
1714 void buildTry( 1742 void buildTry(
1715 {TryStatementInfo tryStatementInfo, 1743 {TryStatementInfo tryStatementInfo,
1716 SubbuildFunction buildTryBlock, 1744 SubbuildFunction buildTryBlock,
1717 List<CatchClauseInfo> catchClauseInfos: const <CatchClauseInfo>[], 1745 List<CatchClauseInfo> catchClauseInfos: const <CatchClauseInfo>[],
1746 SubbuildFunction buildFinallyBlock,
1718 ClosureClassMap closureClassMap}) { 1747 ClosureClassMap closureClassMap}) {
1719 assert(isOpen); 1748 assert(isOpen);
1720 1749
1721 // Catch handlers are in scope for their body. The CPS translation of 1750 // Catch handlers are in scope for their body. The CPS translation of
1722 // [[try tryBlock catch (e) catchBlock; successor]] is: 1751 // [[try tryBlock catch (e) catchBlock; successor]] is:
1723 // 1752 //
1724 // let cont join(v0, v1, ...) = [[successor]] in 1753 // let cont join(v0, v1, ...) = [[successor]] in
1725 // let mutable m0 = x0 in 1754 // let mutable m0 = x0 in
1726 // let mutable m1 = x1 in 1755 // let mutable m1 = x1 in
1727 // ... 1756 // ...
(...skipping 12 matching lines...) Expand all
1740 // 1769 //
1741 // In other words, both the try and catch block are in the scope of the 1770 // In other words, both the try and catch block are in the scope of the
1742 // join-point continuation, and they are both in the scope of a sequence 1771 // join-point continuation, and they are both in the scope of a sequence
1743 // of mutable bindings for the variables assigned in the try. The join- 1772 // of mutable bindings for the variables assigned in the try. The join-
1744 // point continuation is not in the scope of these mutable bindings. 1773 // point continuation is not in the scope of these mutable bindings.
1745 // The tryBlock is in the scope of a binding for the catch handler. Each 1774 // The tryBlock is in the scope of a binding for the catch handler. Each
1746 // instruction (specifically, each call) in the tryBlock is in the dynamic 1775 // instruction (specifically, each call) in the tryBlock is in the dynamic
1747 // scope of the handler. The mutable bindings are dereferenced at the end 1776 // scope of the handler. The mutable bindings are dereferenced at the end
1748 // of the try block and at the beginning of the catch block, so the 1777 // of the try block and at the beginning of the catch block, so the
1749 // variables are unboxed in the catch block and at the join point. 1778 // variables are unboxed in the catch block and at the join point.
1750 JumpCollector join = new ForwardJumpCollector(environment); 1779 if (catchClauseInfos.isNotEmpty) {
1751 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); 1780 JumpCollector join = new ForwardJumpCollector(environment);
1752 1781 IrBuilder tryCatchBuilder = makeDelimitedBuilder();
1753 // Variables treated as mutable in a try are not mutable outside of it. 1782
1754 // Work with a copy of the outer builder's mutable variables. 1783 // Variables treated as mutable in a try are not mutable outside of it.
1755 tryCatchBuilder.mutableVariables = 1784 // Work with a copy of the outer builder's mutable variables.
1756 new Map<Local, ir.MutableVariable>.from(mutableVariables); 1785 tryCatchBuilder.mutableVariables =
1757 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) { 1786 new Map<Local, ir.MutableVariable>.from(mutableVariables);
1758 assert(!tryCatchBuilder.isInMutableVariable(variable)); 1787 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1759 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable); 1788 assert(!tryCatchBuilder.isInMutableVariable(variable));
1760 tryCatchBuilder.makeMutableVariable(variable); 1789 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable);
1761 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); 1790 tryCatchBuilder.makeMutableVariable(variable);
1791 tryCatchBuilder.declareLocalVariable(variable, initialValue: value);
1792 }
1793
1794 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
1795
1796 void interceptJump(JumpCollector collector) {
1797 collector.enterTry(tryStatementInfo.boxedOnEntry);
1798 }
1799 void restoreJump(JumpCollector collector) {
1800 collector.leaveTry();
1801 }
1802 tryBuilder.state.breakCollectors.forEach(interceptJump);
1803 tryBuilder.state.continueCollectors.forEach(interceptJump);
1804 buildTryBlock(tryBuilder);
1805 if (tryBuilder.isOpen) {
1806 interceptJump(join);
1807 tryBuilder.jumpTo(join);
1808 restoreJump(join);
1809 }
1810 tryBuilder.state.breakCollectors.forEach(restoreJump);
1811 tryBuilder.state.continueCollectors.forEach(restoreJump);
1812
1813 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
1814 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1815 assert(catchBuilder.isInMutableVariable(variable));
1816 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable);
1817 // After this point, the variables that were boxed on entry to the try
1818 // are no longer treated as mutable.
1819 catchBuilder.removeMutableVariable(variable);
1820 catchBuilder.environment.update(variable, value);
1821 }
1822
1823 // Handlers are always translated as having both exception and stack trace
1824 // parameters. Multiple clauses do not have to use the same names for
1825 // them. Choose the first of each as the name hint for the respective
1826 // handler parameter.
1827 ir.Parameter exceptionParameter =
1828 new ir.Parameter(catchClauseInfos.first.exceptionVariable);
1829 LocalVariableElement traceVariable;
1830 CatchClauseInfo catchAll;
1831 for (int i = 0; i < catchClauseInfos.length; ++i) {
1832 CatchClauseInfo info = catchClauseInfos[i];
1833 if (info.type == null) {
1834 catchAll = info;
1835 catchClauseInfos.length = i;
1836 break;
1837 }
1838 if (traceVariable == null) {
1839 traceVariable = info.stackTraceVariable;
1840 }
1841 }
1842 ir.Parameter traceParameter = new ir.Parameter(traceVariable);
1843 // Expand multiple catch clauses into an explicit if/then/else. Iterate
1844 // them in reverse so the current block becomes the next else block.
1845 ir.Expression catchBody;
1846 if (catchAll == null) {
1847 catchBody = new ir.Rethrow();
1848 } else {
1849 IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
1850 clauseBuilder.declareLocalVariable(catchAll.exceptionVariable,
1851 initialValue: exceptionParameter);
1852 if (catchAll.stackTraceVariable != null) {
1853 clauseBuilder.declareLocalVariable(catchAll.stackTraceVariable,
1854 initialValue: traceParameter);
1855 }
1856 catchAll.buildCatchBlock(clauseBuilder);
1857 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1858 catchBody = clauseBuilder._root;
1859 }
1860 for (CatchClauseInfo clause in catchClauseInfos.reversed) {
1861 IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
1862 clauseBuilder.declareLocalVariable(clause.exceptionVariable,
1863 initialValue: exceptionParameter);
1864 if (clause.stackTraceVariable != null) {
1865 clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
1866 initialValue: traceParameter);
1867 }
1868 clause.buildCatchBlock(clauseBuilder);
1869 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1870 ir.Continuation thenContinuation = new ir.Continuation([]);
1871 thenContinuation.body = clauseBuilder._root;
1872 ir.Continuation elseContinuation = new ir.Continuation([]);
1873 elseContinuation.body = catchBody;
1874
1875 // Build the type test guarding this clause. We can share the
1876 // environment with the nested builder because this part cannot mutate
1877 // it.
1878 IrBuilder checkBuilder = catchBuilder.makeDelimitedBuilder(environment);
1879 ir.Primitive typeMatches =
1880 checkBuilder.buildTypeOperator(exceptionParameter,
1881 clause.type,
1882 isTypeTest: true);
1883 checkBuilder.add(new ir.LetCont.many([thenContinuation,
1884 elseContinuation],
1885 new ir.Branch(new ir.IsTrue(typeMatches),
1886 thenContinuation,
1887 elseContinuation)));
1888 catchBody = checkBuilder._root;
1889 }
1890
1891 List<ir.Parameter> catchParameters =
1892 <ir.Parameter>[exceptionParameter, traceParameter];
1893 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1894 catchBuilder.add(catchBody);
1895 catchContinuation.body = catchBuilder._root;
1896
1897 tryCatchBuilder.add(
1898 new ir.LetHandler(catchContinuation, tryBuilder._root));
1899 add(new ir.LetCont(join.continuation, tryCatchBuilder._root));
1900 environment = join.environment;
1901 } else {
1902 // Try/finally.
1903 JumpCollector join = new ForwardJumpCollector(environment);
1904 IrBuilder tryFinallyBuilder = makeDelimitedBuilder();
1905
1906 tryFinallyBuilder.mutableVariables =
1907 new Map<Local, ir.MutableVariable>.from(mutableVariables);
1908 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1909 assert(!tryFinallyBuilder.isInMutableVariable(variable));
1910 ir.Primitive value = tryFinallyBuilder.buildLocalVariableGet(variable);
1911 tryFinallyBuilder.makeMutableVariable(variable);
1912 tryFinallyBuilder.declareLocalVariable(variable, initialValue: value);
1913 }
1914
1915 IrBuilder tryBuilder = tryFinallyBuilder.makeDelimitedBuilder();
1916
1917 JumpCollector interceptJump(JumpCollector collector) {
1918 JumpCollector result =
1919 new ForwardJumpCollector(environment, target: collector.target);
1920 result.enterTry(tryStatementInfo.boxedOnEntry);
1921 return result;
1922 }
1923 void restoreJump(JumpCollector collector) {
1924 collector.leaveTry();
1925 }
1926 List<JumpCollector> savedBreaks = tryBuilder.state.breakCollectors;
1927 List<JumpCollector> savedContinues = tryBuilder.state.continueCollectors;
1928 JumpCollector savedReturn = tryBuilder.state.returnCollector;
1929
1930 List<JumpCollector> newBreaks = tryBuilder.state.breakCollectors =
1931 savedBreaks.map(interceptJump).toList();
1932 List<JumpCollector> newContinues = tryBuilder.state.continueCollectors =
1933 savedContinues.map(interceptJump).toList();
1934 JumpCollector newReturn = tryBuilder.state.returnCollector =
1935 new ForwardJumpCollector(environment, hasExtraArgument: true);
1936 newReturn.enterTry(tryStatementInfo.boxedOnEntry);
1937 buildTryBlock(tryBuilder);
1938 if (tryBuilder.isOpen) {
1939 // To cover control falling off the end of the try block, the finally
1940 // code is translated at the join point. This ensures that it is
1941 // correctly outside the scope of the catch handler.
1942 join.enterTry(tryStatementInfo.boxedOnEntry);
1943 tryBuilder.jumpTo(join);
1944 join.leaveTry();
1945 }
1946 newBreaks.forEach(restoreJump);
1947 newContinues.forEach(restoreJump);
1948 newReturn.leaveTry();
1949 tryBuilder.state.breakCollectors = savedBreaks;
1950 tryBuilder.state.continueCollectors = savedContinues;
1951 tryBuilder.state.returnCollector = savedReturn;
1952
1953 IrBuilder catchBuilder = tryFinallyBuilder.makeDelimitedBuilder();
1954 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1955 assert(catchBuilder.isInMutableVariable(variable));
1956 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable);
1957 catchBuilder.removeMutableVariable(variable);
1958 catchBuilder.environment.update(variable, value);
1959 }
1960
1961 buildFinallyBlock(catchBuilder);
1962 if (catchBuilder.isOpen) {
1963 catchBuilder.add(new ir.Rethrow());
1964 catchBuilder._current = null;
1965 }
1966 List<ir.Parameter> catchParameters =
1967 <ir.Parameter>[new ir.Parameter(null), new ir.Parameter(null)];
1968 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1969 catchContinuation.body = catchBuilder._root;
1970 tryFinallyBuilder.add(
1971 new ir.LetHandler(catchContinuation, tryBuilder._root));
1972
1973 // Build a list of continuations for jumps from the try block and
1974 // duplicate the finally code before jumping to the actual target.
1975 List<ir.Continuation> exits = <ir.Continuation>[join.continuation];
1976 void addJump(JumpCollector newCollector,
1977 JumpCollector originalCollector) {
1978 if (newCollector.isEmpty) return;
1979 IrBuilder builder = makeDelimitedBuilder(newCollector.environment);
1980 buildFinallyBlock(builder);
1981 if (builder.isOpen) builder.jumpTo(originalCollector);
1982 newCollector.continuation.body = builder._root;
1983 exits.add(newCollector.continuation);
1984 }
1985 for (int i = 0; i < newBreaks.length; ++i) {
1986 addJump(newBreaks[i], savedBreaks[i]);
1987 }
1988 for (int i = 0; i < newContinues.length; ++i) {
1989 addJump(newContinues[i], savedContinues[i]);
1990 }
1991 if (!newReturn.isEmpty) {
1992 IrBuilder builder = makeDelimitedBuilder(newReturn.environment);
1993 ir.Primitive value = builder.environment.discard(1);
1994 buildFinallyBlock(builder);
1995 if (builder.isOpen) builder.buildReturn(value);
1996 newReturn.continuation.body = builder._root;
1997 exits.add(newReturn.continuation);
1998 }
1999 add(new ir.LetCont.many(exits, tryFinallyBuilder._root));
2000 environment = join.environment;
2001 buildFinallyBlock(this);
1762 } 2002 }
1763
1764 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
1765
1766 void interceptJumps(JumpCollector collector) {
1767 collector.enterTry(tryStatementInfo.boxedOnEntry);
1768 }
1769 void restoreJumps(JumpCollector collector) {
1770 collector.leaveTry();
1771 }
1772 tryBuilder.state.breakCollectors.forEach(interceptJumps);
1773 tryBuilder.state.continueCollectors.forEach(interceptJumps);
1774 buildTryBlock(tryBuilder);
1775 if (tryBuilder.isOpen) {
1776 interceptJumps(join);
1777 tryBuilder.jumpTo(join);
1778 restoreJumps(join);
1779 }
1780 tryBuilder.state.breakCollectors.forEach(restoreJumps);
1781 tryBuilder.state.continueCollectors.forEach(restoreJumps);
1782
1783 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
1784 for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
1785 assert(catchBuilder.isInMutableVariable(variable));
1786 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable);
1787 // After this point, the variables that were boxed on entry to the try
1788 // are no longer treated as mutable.
1789 catchBuilder.removeMutableVariable(variable);
1790 catchBuilder.environment.update(variable, value);
1791 }
1792
1793 // Handlers are always translated as having both exception and stack trace
1794 // parameters. Multiple clauses do not have to use the same names for
1795 // them. Choose the first of each as the name hint for the respective
1796 // handler parameter.
1797 ir.Parameter exceptionParameter =
1798 new ir.Parameter(catchClauseInfos.first.exceptionVariable);
1799 LocalVariableElement traceVariable;
1800 CatchClauseInfo catchAll;
1801 for (int i = 0; i < catchClauseInfos.length; ++i) {
1802 CatchClauseInfo info = catchClauseInfos[i];
1803 if (info.type == null) {
1804 catchAll = info;
1805 catchClauseInfos.length = i;
1806 break;
1807 }
1808 if (traceVariable == null) {
1809 traceVariable = info.stackTraceVariable;
1810 }
1811 }
1812 ir.Parameter traceParameter = new ir.Parameter(traceVariable);
1813 // Expand multiple catch clauses into an explicit if/then/else. Iterate
1814 // them in reverse so the current block becomes the next else block.
1815 ir.Expression catchBody;
1816 if (catchAll == null) {
1817 catchBody = new ir.Rethrow();
1818 } else {
1819 IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
1820 clauseBuilder.declareLocalVariable(catchAll.exceptionVariable,
1821 initialValue: exceptionParameter);
1822 if (catchAll.stackTraceVariable != null) {
1823 clauseBuilder.declareLocalVariable(catchAll.stackTraceVariable,
1824 initialValue: traceParameter);
1825 }
1826 catchAll.buildCatchBlock(clauseBuilder);
1827 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1828 catchBody = clauseBuilder._root;
1829 }
1830 for (CatchClauseInfo clause in catchClauseInfos.reversed) {
1831 IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
1832 clauseBuilder.declareLocalVariable(clause.exceptionVariable,
1833 initialValue: exceptionParameter);
1834 if (clause.stackTraceVariable != null) {
1835 clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
1836 initialValue: traceParameter);
1837 }
1838 clause.buildCatchBlock(clauseBuilder);
1839 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1840 ir.Continuation thenContinuation = new ir.Continuation([]);
1841 thenContinuation.body = clauseBuilder._root;
1842 ir.Continuation elseContinuation = new ir.Continuation([]);
1843 elseContinuation.body = catchBody;
1844
1845 // Build the type test guarding this clause. We can share the environment
1846 // with the nested builder because this part cannot mutate it.
1847 IrBuilder checkBuilder = catchBuilder.makeDelimitedBuilder(environment);
1848 ir.Primitive typeMatches =
1849 checkBuilder.buildTypeOperator(exceptionParameter,
1850 clause.type,
1851 isTypeTest: true);
1852 checkBuilder.add(new ir.LetCont.many([thenContinuation, elseContinuation],
1853 new ir.Branch(new ir.IsTrue(typeMatches),
1854 thenContinuation,
1855 elseContinuation)));
1856 catchBody = checkBuilder._root;
1857 }
1858
1859 List<ir.Parameter> catchParameters =
1860 <ir.Parameter>[exceptionParameter, traceParameter];
1861 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1862 catchBuilder.add(catchBody);
1863 catchContinuation.body = catchBuilder._root;
1864
1865 tryCatchBuilder.add(
1866 new ir.LetHandler(catchContinuation, tryBuilder._root));
1867 add(new ir.LetCont(join.continuation, tryCatchBuilder._root));
1868 environment = join.environment;
1869 } 2003 }
1870 2004
1871 /// Create a return statement `return value;` or `return;` if [value] is 2005 /// Create a return statement `return value;` or `return;` if [value] is
1872 /// null. 2006 /// null.
1873 void buildReturn([ir.Primitive value]) { 2007 void buildReturn([ir.Primitive value]) {
1874 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 2008 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
1875 // where (C', x) = Build(e, C) 2009 // where (C', x) = Build(e, C)
1876 // 2010 //
1877 // Return without a subexpression is translated as if it were return null. 2011 // Return without a subexpression is translated as if it were return null.
1878 assert(isOpen); 2012 assert(isOpen);
1879 if (value == null) { 2013 if (value == null) {
1880 value = buildNullConstant(); 2014 value = buildNullConstant();
1881 } 2015 }
1882 add(new ir.InvokeContinuation(state.returnContinuation, [value])); 2016 if (state.returnCollector == null) {
1883 _current = null; 2017 add(new ir.InvokeContinuation(state.returnContinuation, [value]));
2018 _current = null;
2019 } else {
2020 // Inside the try block of try/finally, all returns go to a join-point
2021 // continuation that contains the finally code. The return value is
2022 // passed as an extra argument.
2023 jumpTo(state.returnCollector, value);
2024 }
1884 } 2025 }
1885 2026
1886 /// Create a blocks of [statements] by applying [build] to all reachable 2027 /// Create a blocks of [statements] by applying [build] to all reachable
1887 /// statements. The first statement is assumed to be reachable. 2028 /// statements. The first statement is assumed to be reachable.
1888 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses 2029 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses
1889 // `List` instead of `Link`. 2030 // `List` instead of `Link`.
1890 void buildBlock(var statements, BuildFunction build) { 2031 void buildBlock(var statements, BuildFunction build) {
1891 // Build(Block(stamements), C) = C' 2032 // Build(Block(stamements), C) = C'
1892 // where C' = statements.fold(Build, C) 2033 // where C' = statements.fold(Build, C)
1893 assert(isOpen); 2034 assert(isOpen);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2030 IrBuilder rightFalseBuilder = rightBuilder.makeDelimitedBuilder(); 2171 IrBuilder rightFalseBuilder = rightBuilder.makeDelimitedBuilder();
2031 2172
2032 // If we don't evaluate the right subexpression, the value of the whole 2173 // If we don't evaluate the right subexpression, the value of the whole
2033 // expression is this constant. 2174 // expression is this constant.
2034 ir.Constant leftBool = emptyBuilder.buildBooleanConstant(isLazyOr); 2175 ir.Constant leftBool = emptyBuilder.buildBooleanConstant(isLazyOr);
2035 // If we do evaluate the right subexpression, the value of the expression 2176 // If we do evaluate the right subexpression, the value of the expression
2036 // is a true or false constant. 2177 // is a true or false constant.
2037 ir.Constant rightTrue = rightTrueBuilder.buildBooleanConstant(true); 2178 ir.Constant rightTrue = rightTrueBuilder.buildBooleanConstant(true);
2038 ir.Constant rightFalse = rightFalseBuilder.buildBooleanConstant(false); 2179 ir.Constant rightFalse = rightFalseBuilder.buildBooleanConstant(false);
2039 2180
2040 // Treat the result values as named values in the environment, so they 2181 // Result values are passed as continuation arguments, which are
2041 // will be treated as arguments to the join-point continuation. 2182 // constructed based on environments. These assertions are a sanity check.
2042 assert(environment.length == emptyBuilder.environment.length); 2183 assert(environment.length == emptyBuilder.environment.length);
2043 assert(environment.length == rightTrueBuilder.environment.length); 2184 assert(environment.length == rightTrueBuilder.environment.length);
2044 assert(environment.length == rightFalseBuilder.environment.length); 2185 assert(environment.length == rightFalseBuilder.environment.length);
2045 // Treat the value of the expression as a local variable so it will get
2046 // a continuation parameter.
2047 environment.extend(null, null);
2048 emptyBuilder.environment.extend(null, leftBool);
2049 rightTrueBuilder.environment.extend(null, rightTrue);
2050 rightFalseBuilder.environment.extend(null, rightFalse);
2051 2186
2052 // Wire up two continuations for the left subexpression, two continuations 2187 // Wire up two continuations for the left subexpression, two continuations
2053 // for the right subexpression, and a three-way join continuation. 2188 // for the right subexpression, and a three-way join continuation.
2054 JumpCollector join = new ForwardJumpCollector(environment); 2189 JumpCollector join =
2055 emptyBuilder.jumpTo(join); 2190 new ForwardJumpCollector(environment, hasExtraArgument: true);
2056 rightTrueBuilder.jumpTo(join); 2191 emptyBuilder.jumpTo(join, leftBool);
2057 rightFalseBuilder.jumpTo(join); 2192 rightTrueBuilder.jumpTo(join, rightTrue);
2193 rightFalseBuilder.jumpTo(join, rightFalse);
2058 ir.Continuation leftTrueContinuation = new ir.Continuation([]); 2194 ir.Continuation leftTrueContinuation = new ir.Continuation([]);
2059 ir.Continuation leftFalseContinuation = new ir.Continuation([]); 2195 ir.Continuation leftFalseContinuation = new ir.Continuation([]);
2060 ir.Continuation rightTrueContinuation = new ir.Continuation([]); 2196 ir.Continuation rightTrueContinuation = new ir.Continuation([]);
2061 ir.Continuation rightFalseContinuation = new ir.Continuation([]); 2197 ir.Continuation rightFalseContinuation = new ir.Continuation([]);
2062 rightTrueContinuation.body = rightTrueBuilder._root; 2198 rightTrueContinuation.body = rightTrueBuilder._root;
2063 rightFalseContinuation.body = rightFalseBuilder._root; 2199 rightFalseContinuation.body = rightFalseBuilder._root;
2064 // The right subexpression has two continuations. 2200 // The right subexpression has two continuations.
2065 rightBuilder.add( 2201 rightBuilder.add(
2066 new ir.LetCont.many(<ir.Continuation>[rightTrueContinuation, 2202 new ir.LetCont.many(<ir.Continuation>[rightTrueContinuation,
2067 rightFalseContinuation], 2203 rightFalseContinuation],
(...skipping 11 matching lines...) Expand all
2079 leftFalseContinuation.body = emptyBuilder._root; 2215 leftFalseContinuation.body = emptyBuilder._root;
2080 } 2216 }
2081 2217
2082 add(new ir.LetCont(join.continuation, 2218 add(new ir.LetCont(join.continuation,
2083 new ir.LetCont.many(<ir.Continuation>[leftTrueContinuation, 2219 new ir.LetCont.many(<ir.Continuation>[leftTrueContinuation,
2084 leftFalseContinuation], 2220 leftFalseContinuation],
2085 new ir.Branch(new ir.IsTrue(leftValue), 2221 new ir.Branch(new ir.IsTrue(leftValue),
2086 leftTrueContinuation, 2222 leftTrueContinuation,
2087 leftFalseContinuation)))); 2223 leftFalseContinuation))));
2088 environment = join.environment; 2224 environment = join.environment;
2089 environment.discard(1); 2225 return environment.discard(1);
2090 // There is always a join parameter for the result value, because it
2091 // is different on at least two paths.
2092 return join.continuation.parameters.last;
2093 } 2226 }
2094 2227
2095 ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y) { 2228 ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y) {
2096 return addPrimitive(new ir.ApplyBuiltinOperator( 2229 return addPrimitive(new ir.ApplyBuiltinOperator(
2097 ir.BuiltinOperator.Identical, <ir.Primitive>[x, y])); 2230 ir.BuiltinOperator.Identical, <ir.Primitive>[x, y]));
2098 } 2231 }
2099 } 2232 }
2100 2233
2101 /// State shared between JsIrBuilders within the same function. 2234 /// State shared between JsIrBuilders within the same function.
2102 /// 2235 ///
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
2623 this.buildCatchBlock}); 2756 this.buildCatchBlock});
2624 } 2757 }
2625 2758
2626 class SwitchCaseInfo { 2759 class SwitchCaseInfo {
2627 final List<ir.Primitive> constants = <ir.Primitive>[]; 2760 final List<ir.Primitive> constants = <ir.Primitive>[];
2628 final SubbuildFunction buildBody; 2761 final SubbuildFunction buildBody;
2629 2762
2630 SwitchCaseInfo(this.buildBody); 2763 SwitchCaseInfo(this.buildBody);
2631 2764
2632 void addConstant(ir.Primitive constant) => constants.add(constant); 2765 void addConstant(ir.Primitive constant) => constants.add(constant);
2633 } 2766 }
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