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

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

Issue 1585503002: dart2js: CPS translation of switches with continue to their labels. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase. Created 4 years, 11 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 '../closure.dart' as closure; 7 import '../closure.dart' as closure;
8 import '../common.dart'; 8 import '../common.dart';
9 import '../common/names.dart' show 9 import '../common/names.dart' show
10 Names, 10 Names,
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 if (hasExtraArgument) _continuationEnvironment.extend(null, null); 159 if (hasExtraArgument) _continuationEnvironment.extend(null, null);
160 } 160 }
161 161
162 /// Construct a collector for collecting only return jumps. 162 /// Construct a collector for collecting only return jumps.
163 /// 163 ///
164 /// There is no jump target, it is implicitly the exit from the function. 164 /// There is no jump target, it is implicitly the exit from the function.
165 /// There is no environment at the destination. 165 /// There is no environment at the destination.
166 JumpCollector.retrn(this._continuation) 166 JumpCollector.retrn(this._continuation)
167 : _continuationEnvironment = null, target = null; 167 : _continuationEnvironment = null, target = null;
168 168
169 /// Construct a collector for collecting goto jumps.
170 ///
171 /// There is no continuation or environment at the destination.
172 JumpCollector.goto(this.target) : _continuationEnvironment = null;
173
169 /// True if the collector has not recorded any jumps to its continuation. 174 /// True if the collector has not recorded any jumps to its continuation.
170 bool get isEmpty; 175 bool get isEmpty;
171 176
172 /// The continuation encapsulated by this collector. 177 /// The continuation encapsulated by this collector.
173 ir.Continuation get continuation; 178 ir.Continuation get continuation;
174 179
175 /// The compile-time environment to be used for translating code in the body 180 /// The compile-time environment to be used for translating code in the body
176 /// of the continuation. 181 /// of the continuation.
177 Environment get environment; 182 Environment get environment;
178 183
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 void addJump(IrBuilder builder, 419 void addJump(IrBuilder builder,
415 [ir.Primitive value, SourceInformation sourceInformation]) { 420 [ir.Primitive value, SourceInformation sourceInformation]) {
416 isEmpty = false; 421 isEmpty = false;
417 builder.add(new ir.InvokeContinuation(continuation, <ir.Primitive>[value], 422 builder.add(new ir.InvokeContinuation(continuation, <ir.Primitive>[value],
418 isEscapingTry: isEscapingTry, 423 isEscapingTry: isEscapingTry,
419 sourceInformation: sourceInformation)); 424 sourceInformation: sourceInformation));
420 builder._current = null; 425 builder._current = null;
421 } 426 }
422 } 427 }
423 428
429 /// Collect 'goto' jumps, continue to a labeled case from within a switch.
430 ///
431 /// These jumps are unrestricted within the switch. They can be forward or
432 /// backward. They are implemented by assigning to a state variable.
433 class GotoJumpCollector extends JumpCollector {
434 bool isEmpty = true;
435 final ir.Continuation continuation = null;
436 final Environment environment = null;
437
438 int _stateVariableIndex;
439 int _stateValue;
440 JumpCollector _breakJoin;
441
442 GotoJumpCollector(JumpTarget target, this._stateVariableIndex,
443 this._stateValue, this._breakJoin) : super.goto(target);
444
445 void addJump(IrBuilder builder,
446 [ir.Primitive value, SourceInformation sourceInformation]) {
447 isEmpty = false;
448 ir.Primitive constant = builder.buildIntegerConstant(_stateValue);
449 builder.environment.index2value[_stateVariableIndex] = constant;
450 builder.jumpTo(_breakJoin);
451 }
452 }
453
424 /// Function for building a node in the context of the current builder. 454 /// Function for building a node in the context of the current builder.
425 typedef ir.Node BuildFunction(node); 455 typedef ir.Node BuildFunction(node);
426 456
427 /// Function for building nodes in the context of the provided [builder]. 457 /// Function for building nodes in the context of the provided [builder].
428 typedef ir.Node SubbuildFunction(IrBuilder builder); 458 typedef ir.Node SubbuildFunction(IrBuilder builder);
429 459
430 /// Mixin that provides encapsulated access to nested builders. 460 /// Mixin that provides encapsulated access to nested builders.
431 abstract class IrBuilderMixin<N> { 461 abstract class IrBuilderMixin<N> {
432 IrBuilder _irBuilder; 462 IrBuilder _irBuilder;
433 463
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 final ExecutableElement executableContext; 555 final ExecutableElement executableContext;
526 ThisParameterLocal(this.executableContext); 556 ThisParameterLocal(this.executableContext);
527 String get name => 'this'; 557 String get name => 'this';
528 toString() => 'ThisParameterLocal($executableContext)'; 558 toString() => 'ThisParameterLocal($executableContext)';
529 } 559 }
530 560
531 /// The IR builder maintains an environment and an IR fragment. 561 /// The IR builder maintains an environment and an IR fragment.
532 /// 562 ///
533 /// The IR fragment is an expression with a hole in it. The hole represents 563 /// The IR fragment is an expression with a hole in it. The hole represents
534 /// the focus where new expressions can be added. The fragment is implemented 564 /// the focus where new expressions can be added. The fragment is implemented
535 /// by [_root] which is the root of the expression and [_current] which is the 565 /// by [root] which is the root of the expression and [_current] which is the
536 /// expression that immediately contains the hole. Not all expressions have a 566 /// expression that immediately contains the hole. Not all expressions have a
537 /// hole (e.g., invocations, which always occur in tail position, do not have a 567 /// hole (e.g., invocations, which always occur in tail position, do not have a
538 /// hole). Expressions with a hole have a plug method. 568 /// hole). Expressions with a hole have a plug method.
539 /// 569 ///
540 /// The environment maintains the reaching definition of each local variable, 570 /// The environment maintains the reaching definition of each local variable,
541 /// including some synthetic locals such as [TypeVariableLocal]. 571 /// including some synthetic locals such as [TypeVariableLocal].
542 /// 572 ///
543 /// Internally, IR builders also maintains a [JumpCollector] stack and tracks 573 /// Internally, IR builders also maintains a [JumpCollector] stack and tracks
544 /// which variables are currently boxed or held in a mutable local variable. 574 /// which variables are currently boxed or held in a mutable local variable.
545 class IrBuilder { 575 class IrBuilder {
546 final List<ir.Parameter> _parameters = <ir.Parameter>[]; 576 final List<ir.Parameter> _parameters = <ir.Parameter>[];
547 577
548 final IrBuilderSharedState state; 578 final IrBuilderSharedState state;
549 579
550 /// A map from variable indexes to their values. 580 /// A map from variable indexes to their values.
551 /// 581 ///
552 /// [BoxLocal]s map to their box. [LocalElement]s that are boxed are not 582 /// [BoxLocal]s map to their box. [LocalElement]s that are boxed are not
553 /// in the map; look up their [BoxLocal] instead. 583 /// in the map; look up their [BoxLocal] instead.
554 Environment environment; 584 Environment environment;
555 585
556 /// A map from mutable local variables to their [ir.MutableVariable]s. 586 /// A map from mutable local variables to their [ir.MutableVariable]s.
557 /// 587 ///
558 /// Mutable variables are treated as boxed. Writes to them are observable 588 /// Mutable variables are treated as boxed. Writes to them are observable
559 /// side effects. 589 /// side effects.
560 Map<Local, ir.MutableVariable> mutableVariables; 590 Map<Local, ir.MutableVariable> mutableVariables;
561 591
562 ir.Expression _root = null; 592 ir.Expression root = null;
563 ir.Expression _current = null; 593 ir.Expression _current = null;
564 594
565 GlobalProgramInformation get program => state.program; 595 GlobalProgramInformation get program => state.program;
566 596
567 IrBuilder(GlobalProgramInformation program, 597 IrBuilder(GlobalProgramInformation program,
568 BackendConstantEnvironment constants, 598 BackendConstantEnvironment constants,
569 ExecutableElement currentElement) 599 ExecutableElement currentElement)
570 : state = new IrBuilderSharedState(program, constants, currentElement), 600 : state = new IrBuilderSharedState(program, constants, currentElement),
571 environment = new Environment.empty(), 601 environment = new Environment.empty(),
572 mutableVariables = <Local, ir.MutableVariable>{}; 602 mutableVariables = <Local, ir.MutableVariable>{};
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 /// mutable variable. 636 /// mutable variable.
607 void removeMutableVariable(Local local) { 637 void removeMutableVariable(Local local) {
608 mutableVariables.remove(local); 638 mutableVariables.remove(local);
609 } 639 }
610 640
611 /// Gets the [MutableVariable] containing the value of [local]. 641 /// Gets the [MutableVariable] containing the value of [local].
612 ir.MutableVariable getMutableVariable(Local local) { 642 ir.MutableVariable getMutableVariable(Local local) {
613 return mutableVariables[local]; 643 return mutableVariables[local];
614 } 644 }
615 645
616 bool get isOpen => _root == null || _current != null; 646 bool get isOpen => root == null || _current != null;
617 647
618 List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters, 648 List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters,
619 {ClosureScope closureScope, 649 {ClosureScope closureScope,
620 ClosureEnvironment env}) { 650 ClosureEnvironment env}) {
621 _createThisParameter(); 651 _createThisParameter();
622 _enterClosureEnvironment(env); 652 _enterClosureEnvironment(env);
623 _enterScope(closureScope); 653 _enterScope(closureScope);
624 parameters.forEach(_createFunctionParameter); 654 parameters.forEach(_createFunctionParameter);
625 return _parameters; 655 return _parameters;
626 } 656 }
627 657
628 /// Creates a parameter for [local] and adds it to the current environment. 658 /// Creates a parameter for [local] and adds it to the current environment.
629 ir.Parameter _createLocalParameter(Local local) { 659 ir.Parameter _createLocalParameter(Local local) {
630 ir.Parameter parameter = new ir.Parameter(local); 660 ir.Parameter parameter = new ir.Parameter(local);
631 _parameters.add(parameter); 661 _parameters.add(parameter);
632 environment.extend(local, parameter); 662 environment.extend(local, parameter);
633 return parameter; 663 return parameter;
634 } 664 }
635 665
636 /// Plug an expression into the 'hole' in the context being accumulated. The 666 /// Plug an expression into the 'hole' in the context being accumulated. The
637 /// empty context (just a hole) is represented by root (and current) being 667 /// empty context (just a hole) is represented by root (and current) being
638 /// null. Since the hole in the current context is filled by this function, 668 /// null. Since the hole in the current context is filled by this function,
639 /// the new hole must be in the newly added expression---which becomes the 669 /// the new hole must be in the newly added expression---which becomes the
640 /// new value of current. 670 /// new value of current.
641 void add(ir.Expression expr) { 671 void add(ir.Expression expr) {
642 assert(isOpen); 672 assert(isOpen);
643 if (_root == null) { 673 if (root == null) {
644 _root = _current = expr; 674 root = _current = expr;
645 } else { 675 } else {
646 _current = _current.plug(expr); 676 _current = _current.plug(expr);
647 } 677 }
648 } 678 }
649 679
650 /// Create and add a new [LetPrim] for [primitive]. 680 /// Create and add a new [LetPrim] for [primitive].
651 ir.Primitive addPrimitive(ir.Primitive primitive) { 681 ir.Primitive addPrimitive(ir.Primitive primitive) {
652 add(new ir.LetPrim(primitive)); 682 add(new ir.LetPrim(primitive));
653 return primitive; 683 return primitive;
654 } 684 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 elseBuilder.jumpTo(join, elseValue); 812 elseBuilder.jumpTo(join, elseValue);
783 813
784 // Build the term 814 // Build the term
785 // let cont join(x, ..., result) = [] in 815 // let cont join(x, ..., result) = [] in
786 // let cont then() = [[thenPart]]; join(v, ...) 816 // let cont then() = [[thenPart]]; join(v, ...)
787 // and else() = [[elsePart]]; join(v, ...) 817 // and else() = [[elsePart]]; join(v, ...)
788 // in 818 // in
789 // if condition (then, else) 819 // if condition (then, else)
790 ir.Continuation thenContinuation = new ir.Continuation([]); 820 ir.Continuation thenContinuation = new ir.Continuation([]);
791 ir.Continuation elseContinuation = new ir.Continuation([]); 821 ir.Continuation elseContinuation = new ir.Continuation([]);
792 thenContinuation.body = thenBuilder._root; 822 thenContinuation.body = thenBuilder.root;
793 elseContinuation.body = elseBuilder._root; 823 elseContinuation.body = elseBuilder.root;
794 add(new ir.LetCont(join.continuation, 824 add(new ir.LetCont(join.continuation,
795 new ir.LetCont.two(thenContinuation, elseContinuation, 825 new ir.LetCont.two(thenContinuation, elseContinuation,
796 new ir.Branch.strict(condition, 826 new ir.Branch.strict(condition,
797 thenContinuation, 827 thenContinuation,
798 elseContinuation)))); 828 elseContinuation))));
799 environment = join.environment; 829 environment = join.environment;
800 return environment.discard(1); 830 return environment.discard(1);
801 } 831 }
802 832
803 /** 833 /**
804 * Add an explicit `return null` for functions that don't have a return 834 * Add an explicit `return null` for functions that don't have a return
805 * statement on each branch. This includes functions with an empty body, 835 * statement on each branch. This includes functions with an empty body,
806 * such as `foo(){ }`. 836 * such as `foo(){ }`.
807 */ 837 */
808 void _ensureReturn() { 838 void _ensureReturn() {
809 if (!isOpen) return; 839 if (!isOpen) return;
810 ir.Constant constant = buildNullConstant(); 840 ir.Constant constant = buildNullConstant();
811 add(new ir.InvokeContinuation(state.returnContinuation, [constant])); 841 add(new ir.InvokeContinuation(state.returnContinuation, [constant]));
812 _current = null; 842 _current = null;
813 } 843 }
814 844
815 /// Create a [ir.FunctionDefinition] using [_root] as the body. 845 /// Create a [ir.FunctionDefinition] using [root] as the body.
816 /// 846 ///
817 /// The protocol for building a function is: 847 /// The protocol for building a function is:
818 /// 1. Call [buildFunctionHeader]. 848 /// 1. Call [buildFunctionHeader].
819 /// 2. Call `buildXXX` methods to build the body. 849 /// 2. Call `buildXXX` methods to build the body.
820 /// 3. Call [makeFunctionDefinition] to finish. 850 /// 3. Call [makeFunctionDefinition] to finish.
821 ir.FunctionDefinition makeFunctionDefinition() { 851 ir.FunctionDefinition makeFunctionDefinition() {
822 _ensureReturn(); 852 _ensureReturn();
823 return new ir.FunctionDefinition( 853 return new ir.FunctionDefinition(
824 state.currentElement, 854 state.currentElement,
825 state.thisParameter, 855 state.thisParameter,
826 state.functionParameters, 856 state.functionParameters,
827 state.returnContinuation, 857 state.returnContinuation,
828 _root); 858 root);
829 } 859 }
830 860
831 /// Create a invocation of the [method] on the super class where the call 861 /// Create a invocation of the [method] on the super class where the call
832 /// structure is defined [callStructure] and the argument values are defined 862 /// structure is defined [callStructure] and the argument values are defined
833 /// by [arguments]. 863 /// by [arguments].
834 ir.Primitive buildSuperMethodInvocation( 864 ir.Primitive buildSuperMethodInvocation(
835 MethodElement method, 865 MethodElement method,
836 CallStructure callStructure, 866 CallStructure callStructure,
837 List<ir.Primitive> arguments, 867 List<ir.Primitive> arguments,
838 {SourceInformation sourceInformation}) { 868 {SourceInformation sourceInformation}) {
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 result = new ir.LetCont(join.continuation, result); 1130 result = new ir.LetCont(join.continuation, result);
1101 } 1131 }
1102 1132
1103 // The then or else term root could be null, but not both. If there is 1133 // The then or else term root could be null, but not both. If there is
1104 // a join then an InvokeContinuation was just added to both of them. If 1134 // a join then an InvokeContinuation was just added to both of them. If
1105 // there is no join, then at least one of them is closed and thus has a 1135 // there is no join, then at least one of them is closed and thus has a
1106 // non-null root by the definition of the predicate isClosed. In the 1136 // non-null root by the definition of the predicate isClosed. In the
1107 // case that one of them is null, it must be the only one that is open 1137 // case that one of them is null, it must be the only one that is open
1108 // and thus contains the new hole in the context. This case is handled 1138 // and thus contains the new hole in the context. This case is handled
1109 // after the branch is plugged into the current hole. 1139 // after the branch is plugged into the current hole.
1110 thenContinuation.body = thenBuilder._root; 1140 thenContinuation.body = thenBuilder.root;
1111 elseContinuation.body = elseBuilder._root; 1141 elseContinuation.body = elseBuilder.root;
1112 1142
1113 add(result); 1143 add(result);
1114 if (join == null) { 1144 if (join == null) {
1115 // At least one subexpression is closed. 1145 // At least one subexpression is closed.
1116 if (thenBuilder.isOpen) { 1146 if (thenBuilder.isOpen) {
1117 if (thenBuilder._root != null) _current = thenBuilder._current; 1147 if (thenBuilder.root != null) _current = thenBuilder._current;
1118 environment = thenBuilder.environment; 1148 environment = thenBuilder.environment;
1119 } else if (elseBuilder.isOpen) { 1149 } else if (elseBuilder.isOpen) {
1120 if (elseBuilder._root != null) _current = elseBuilder._current; 1150 if (elseBuilder.root != null) _current = elseBuilder._current;
1121 environment = elseBuilder.environment; 1151 environment = elseBuilder.environment;
1122 } else { 1152 } else {
1123 _current = null; 1153 _current = null;
1124 } 1154 }
1125 } else { 1155 } else {
1126 environment = join.environment; 1156 environment = join.environment;
1127 } 1157 }
1128 } 1158 }
1129 1159
1130 void jumpTo(JumpCollector collector, 1160 void jumpTo(JumpCollector collector,
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 } else { 1266 } else {
1237 updateBuilder = innerBodyBuilder; 1267 updateBuilder = innerBodyBuilder;
1238 } 1268 }
1239 updateBuilder._enterForLoopUpdate(closureScope, loopVariables); 1269 updateBuilder._enterForLoopUpdate(closureScope, loopVariables);
1240 buildUpdate(updateBuilder); 1270 buildUpdate(updateBuilder);
1241 if (updateBuilder.isOpen) updateBuilder.jumpTo(loop); 1271 if (updateBuilder.isOpen) updateBuilder.jumpTo(loop);
1242 // Connect the inner and outer body builders. This is done only after 1272 // Connect the inner and outer body builders. This is done only after
1243 // it is guaranteed that the updateBuilder has a non-empty term. 1273 // it is guaranteed that the updateBuilder has a non-empty term.
1244 if (hasContinues) { 1274 if (hasContinues) {
1245 outerBodyBuilder.add(new ir.LetCont(continueCollector.continuation, 1275 outerBodyBuilder.add(new ir.LetCont(continueCollector.continuation,
1246 innerBodyBuilder._root)); 1276 innerBodyBuilder.root));
1247 continueCollector.continuation.body = updateBuilder._root; 1277 continueCollector.continuation.body = updateBuilder.root;
1248 } else { 1278 } else {
1249 outerBodyBuilder.add(innerBodyBuilder._root); 1279 outerBodyBuilder.add(innerBodyBuilder.root);
1250 } 1280 }
1251 1281
1252 // Create loop exit and body entry continuations and a branch to them. 1282 // Create loop exit and body entry continuations and a branch to them.
1253 ir.Continuation exitContinuation = new ir.Continuation([]); 1283 ir.Continuation exitContinuation = new ir.Continuation([]);
1254 ir.Continuation bodyContinuation = new ir.Continuation([]); 1284 ir.Continuation bodyContinuation = new ir.Continuation([]);
1255 bodyContinuation.body = outerBodyBuilder._root; 1285 bodyContinuation.body = outerBodyBuilder.root;
1256 // Note the order of continuations: the first one is the one that will 1286 // Note the order of continuations: the first one is the one that will
1257 // be filled by LetCont.plug. 1287 // be filled by LetCont.plug.
1258 ir.LetCont branch = 1288 ir.LetCont branch =
1259 new ir.LetCont.two(exitContinuation, bodyContinuation, 1289 new ir.LetCont.two(exitContinuation, bodyContinuation,
1260 new ir.Branch.strict(condition, 1290 new ir.Branch.strict(condition,
1261 bodyContinuation, 1291 bodyContinuation,
1262 exitContinuation)); 1292 exitContinuation));
1263 // If there are breaks in the body, then there must be a join-point 1293 // If there are breaks in the body, then there must be a join-point
1264 // continuation for the normal exit and the breaks. Otherwise, the 1294 // continuation for the normal exit and the breaks. Otherwise, the
1265 // successor is translated in the hole in the exit continuation. 1295 // successor is translated in the hole in the exit continuation.
1266 bool hasBreaks = !breakCollector.isEmpty; 1296 bool hasBreaks = !breakCollector.isEmpty;
1267 ir.LetCont letBreak; 1297 ir.LetCont letBreak;
1268 if (hasBreaks) { 1298 if (hasBreaks) {
1269 IrBuilder exitBuilder = makeDelimitedBuilder(); 1299 IrBuilder exitBuilder = makeDelimitedBuilder();
1270 exitBuilder.jumpTo(breakCollector); 1300 exitBuilder.jumpTo(breakCollector);
1271 exitContinuation.body = exitBuilder._root; 1301 exitContinuation.body = exitBuilder.root;
1272 letBreak = new ir.LetCont(breakCollector.continuation, branch); 1302 letBreak = new ir.LetCont(breakCollector.continuation, branch);
1273 add(letBreak); 1303 add(letBreak);
1274 environment = breakCollector.environment; 1304 environment = breakCollector.environment;
1275 } else { 1305 } else {
1276 add(branch); 1306 add(branch);
1277 } 1307 }
1278 } 1308 }
1279 1309
1280 /// Creates a for-in loop, `for (v in e) b`. 1310 /// Creates a for-in loop, `for (v in e) b`.
1281 /// 1311 ///
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1404 state.continueCollectors.removeLast(); 1434 state.continueCollectors.removeLast();
1405 if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop); 1435 if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop);
1406 1436
1407 // Create body entry and loop exit continuations and a branch to them. 1437 // Create body entry and loop exit continuations and a branch to them.
1408 // 1438 //
1409 // let cont exit() = [ ] 1439 // let cont exit() = [ ]
1410 // and body() = <<BODY>> 1440 // and body() = <<BODY>>
1411 // in branch condition (body, exit) 1441 // in branch condition (body, exit)
1412 ir.Continuation exitContinuation = new ir.Continuation([]); 1442 ir.Continuation exitContinuation = new ir.Continuation([]);
1413 ir.Continuation bodyContinuation = new ir.Continuation([]); 1443 ir.Continuation bodyContinuation = new ir.Continuation([]);
1414 bodyContinuation.body = bodyBuilder._root; 1444 bodyContinuation.body = bodyBuilder.root;
1415 // Note the order of continuations: the first one is the one that will 1445 // Note the order of continuations: the first one is the one that will
1416 // be filled by LetCont.plug. 1446 // be filled by LetCont.plug.
1417 ir.LetCont branch = 1447 ir.LetCont branch =
1418 new ir.LetCont.two(exitContinuation, bodyContinuation, 1448 new ir.LetCont.two(exitContinuation, bodyContinuation,
1419 new ir.Branch.strict(condition, 1449 new ir.Branch.strict(condition,
1420 bodyContinuation, 1450 bodyContinuation,
1421 exitContinuation)); 1451 exitContinuation));
1422 // If there are breaks in the body, then there must be a join-point 1452 // If there are breaks in the body, then there must be a join-point
1423 // continuation for the normal exit and the breaks. Otherwise, the 1453 // continuation for the normal exit and the breaks. Otherwise, the
1424 // successor is translated in the hole in the exit continuation. 1454 // successor is translated in the hole in the exit continuation.
1425 bool hasBreaks = !breakCollector.isEmpty; 1455 bool hasBreaks = !breakCollector.isEmpty;
1426 ir.LetCont letBreak; 1456 ir.LetCont letBreak;
1427 if (hasBreaks) { 1457 if (hasBreaks) {
1428 IrBuilder exitBuilder = makeDelimitedBuilder(); 1458 IrBuilder exitBuilder = makeDelimitedBuilder();
1429 exitBuilder.jumpTo(breakCollector); 1459 exitBuilder.jumpTo(breakCollector);
1430 exitContinuation.body = exitBuilder._root; 1460 exitContinuation.body = exitBuilder.root;
1431 letBreak = new ir.LetCont(breakCollector.continuation, branch); 1461 letBreak = new ir.LetCont(breakCollector.continuation, branch);
1432 add(letBreak); 1462 add(letBreak);
1433 environment = breakCollector.environment; 1463 environment = breakCollector.environment;
1434 } else { 1464 } else {
1435 add(branch); 1465 add(branch);
1436 } 1466 }
1437 } 1467 }
1438 1468
1439 /// Creates a while loop in which the condition and body are created by 1469 /// Creates a while loop in which the condition and body are created by
1440 /// [buildCondition] and [buildBody], respectively. 1470 /// [buildCondition] and [buildBody], respectively.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1479 buildBody(bodyBuilder); 1509 buildBody(bodyBuilder);
1480 assert(state.breakCollectors.last == breakCollector); 1510 assert(state.breakCollectors.last == breakCollector);
1481 assert(state.continueCollectors.last == loop); 1511 assert(state.continueCollectors.last == loop);
1482 state.breakCollectors.removeLast(); 1512 state.breakCollectors.removeLast();
1483 state.continueCollectors.removeLast(); 1513 state.continueCollectors.removeLast();
1484 if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop); 1514 if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop);
1485 1515
1486 // Create body entry and loop exit continuations and a branch to them. 1516 // Create body entry and loop exit continuations and a branch to them.
1487 ir.Continuation exitContinuation = new ir.Continuation([]); 1517 ir.Continuation exitContinuation = new ir.Continuation([]);
1488 ir.Continuation bodyContinuation = new ir.Continuation([]); 1518 ir.Continuation bodyContinuation = new ir.Continuation([]);
1489 bodyContinuation.body = bodyBuilder._root; 1519 bodyContinuation.body = bodyBuilder.root;
1490 // Note the order of continuations: the first one is the one that will 1520 // Note the order of continuations: the first one is the one that will
1491 // be filled by LetCont.plug. 1521 // be filled by LetCont.plug.
1492 ir.LetCont branch = 1522 ir.LetCont branch =
1493 new ir.LetCont.two(exitContinuation, bodyContinuation, 1523 new ir.LetCont.two(exitContinuation, bodyContinuation,
1494 new ir.Branch.strict(condition, 1524 new ir.Branch.strict(condition,
1495 bodyContinuation, 1525 bodyContinuation,
1496 exitContinuation)); 1526 exitContinuation));
1497 // If there are breaks in the body, then there must be a join-point 1527 // If there are breaks in the body, then there must be a join-point
1498 // continuation for the normal exit and the breaks. Otherwise, the 1528 // continuation for the normal exit and the breaks. Otherwise, the
1499 // successor is translated in the hole in the exit continuation. 1529 // successor is translated in the hole in the exit continuation.
1500 bool hasBreaks = !breakCollector.isEmpty; 1530 bool hasBreaks = !breakCollector.isEmpty;
1501 ir.LetCont letBreak; 1531 ir.LetCont letBreak;
1502 if (hasBreaks) { 1532 if (hasBreaks) {
1503 IrBuilder exitBuilder = makeDelimitedBuilder(); 1533 IrBuilder exitBuilder = makeDelimitedBuilder();
1504 exitBuilder.jumpTo(breakCollector); 1534 exitBuilder.jumpTo(breakCollector);
1505 exitContinuation.body = exitBuilder._root; 1535 exitContinuation.body = exitBuilder.root;
1506 letBreak = new ir.LetCont(breakCollector.continuation, branch); 1536 letBreak = new ir.LetCont(breakCollector.continuation, branch);
1507 add(letBreak); 1537 add(letBreak);
1508 environment = breakCollector.environment; 1538 environment = breakCollector.environment;
1509 } else { 1539 } else {
1510 add(branch); 1540 add(branch);
1511 } 1541 }
1512 } 1542 }
1513 1543
1514 1544
1515 /// Creates a do-while loop. 1545 /// Creates a do-while loop.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1562 // let cont exit() = break(v, ...) 1592 // let cont exit() = break(v, ...)
1563 // and repeat() = loop(v, ...) 1593 // and repeat() = loop(v, ...)
1564 // in branch cond (repeat, exit) 1594 // in branch cond (repeat, exit)
1565 IrBuilder continueBuilder = loopBuilder.makeDelimitedBuilder(); 1595 IrBuilder continueBuilder = loopBuilder.makeDelimitedBuilder();
1566 continueBuilder.environment = continueCollector.environment; 1596 continueBuilder.environment = continueCollector.environment;
1567 ir.Primitive condition = buildCondition(continueBuilder); 1597 ir.Primitive condition = buildCondition(continueBuilder);
1568 1598
1569 ir.Continuation exitContinuation = new ir.Continuation([]); 1599 ir.Continuation exitContinuation = new ir.Continuation([]);
1570 IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder(); 1600 IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder();
1571 exitBuilder.jumpTo(breakCollector); 1601 exitBuilder.jumpTo(breakCollector);
1572 exitContinuation.body = exitBuilder._root; 1602 exitContinuation.body = exitBuilder.root;
1573 ir.Continuation repeatContinuation = new ir.Continuation([]); 1603 ir.Continuation repeatContinuation = new ir.Continuation([]);
1574 IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder(); 1604 IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder();
1575 repeatBuilder.jumpTo(loop); 1605 repeatBuilder.jumpTo(loop);
1576 repeatContinuation.body = repeatBuilder._root; 1606 repeatContinuation.body = repeatBuilder.root;
1577 1607
1578 continueBuilder.add( 1608 continueBuilder.add(
1579 new ir.LetCont.two(exitContinuation, repeatContinuation, 1609 new ir.LetCont.two(exitContinuation, repeatContinuation,
1580 new ir.Branch.strict(condition, 1610 new ir.Branch.strict(condition,
1581 repeatContinuation, 1611 repeatContinuation,
1582 exitContinuation))); 1612 exitContinuation)));
1583 continueCollector.continuation.body = continueBuilder._root; 1613 continueCollector.continuation.body = continueBuilder.root;
1584 1614
1585 // Construct the loop continuation (i.e., the body and condition). 1615 // Construct the loop continuation (i.e., the body and condition).
1586 // <Loop> = 1616 // <Loop> =
1587 // let cont continue(x, ...) = 1617 // let cont continue(x, ...) =
1588 // <Continue> 1618 // <Continue>
1589 // in [[body]]; continue(v, ...) 1619 // in [[body]]; continue(v, ...)
1590 loopBuilder.add( 1620 loopBuilder.add(
1591 new ir.LetCont(continueCollector.continuation, 1621 new ir.LetCont(continueCollector.continuation,
1592 bodyBuilder._root)); 1622 bodyBuilder.root));
1593 1623
1594 // And tie it all together. 1624 // And tie it all together.
1595 add(new ir.LetCont(breakCollector.continuation, loopBuilder._root)); 1625 add(new ir.LetCont(breakCollector.continuation, loopBuilder.root));
1596 environment = breakCollector.environment; 1626 environment = breakCollector.environment;
1597 } 1627 }
1598 1628
1599 void buildSimpleSwitch(JumpTarget target, 1629 void buildSimpleSwitch(JumpCollector join,
1600 ir.Primitive value,
1601 List<SwitchCaseInfo> cases, 1630 List<SwitchCaseInfo> cases,
1602 SwitchCaseInfo defaultCase, 1631 SubbuildFunction buildDefaultBody) {
1603 Element error,
1604 SourceInformation sourceInformation) {
1605 assert(isOpen);
1606 JumpCollector join = new ForwardJumpCollector(environment, target: target);
1607
1608 IrBuilder casesBuilder = makeDelimitedBuilder(); 1632 IrBuilder casesBuilder = makeDelimitedBuilder();
1609 casesBuilder.state.breakCollectors.add(join);
1610 for (SwitchCaseInfo caseInfo in cases) { 1633 for (SwitchCaseInfo caseInfo in cases) {
1611 buildConditionsFrom(int index) => (IrBuilder builder) { 1634 ir.Primitive condition = caseInfo.buildCondition(casesBuilder);
1612 ir.Primitive comparison = builder.buildIdentical(
1613 value, caseInfo.constants[index]);
1614 return (index == caseInfo.constants.length - 1)
1615 ? comparison
1616 : builder.buildLogicalOperator(
1617 comparison, buildConditionsFrom(index + 1), isLazyOr: true);
1618 };
1619
1620 ir.Primitive condition = buildConditionsFrom(0)(casesBuilder);
1621 IrBuilder thenBuilder = makeDelimitedBuilder(); 1635 IrBuilder thenBuilder = makeDelimitedBuilder();
1622 caseInfo.buildBody(thenBuilder); 1636 caseInfo.buildBody(thenBuilder);
1623 if (thenBuilder.isOpen) {
1624 // It is a runtime error to reach the end of a switch case, unless
1625 // it is the last case.
1626 if (caseInfo == cases.last && defaultCase == null) {
1627 thenBuilder.jumpTo(join);
1628 } else {
1629 ir.Primitive exception = thenBuilder.buildInvokeStatic(
1630 error,
1631 new Selector.fromElement(error),
1632 <ir.Primitive>[],
1633 sourceInformation);
1634 thenBuilder.buildThrow(exception);
1635 }
1636 }
1637
1638 ir.Continuation thenContinuation = new ir.Continuation([]); 1637 ir.Continuation thenContinuation = new ir.Continuation([]);
1639 thenContinuation.body = thenBuilder._root; 1638 thenContinuation.body = thenBuilder.root;
1640 ir.Continuation elseContinuation = new ir.Continuation([]); 1639 ir.Continuation elseContinuation = new ir.Continuation([]);
1641 // A LetCont.many term has a hole as the body of the first listed 1640 // A LetCont.two term has a hole as the body of the first listed
1642 // continuation, to be plugged by the translation. Therefore put the 1641 // continuation, to be plugged by the translation. Therefore put the
1643 // else continuation first. 1642 // else continuation first.
1644 casesBuilder.add( 1643 casesBuilder.add(
1645 new ir.LetCont.two(elseContinuation, thenContinuation, 1644 new ir.LetCont.two(elseContinuation, thenContinuation,
1646 new ir.Branch.strict(condition, 1645 new ir.Branch.strict(condition,
1647 thenContinuation, 1646 thenContinuation,
1648 elseContinuation))); 1647 elseContinuation)));
1649 } 1648 }
1650 1649
1651 if (defaultCase != null) { 1650 if (buildDefaultBody == null) {
1652 defaultCase.buildBody(casesBuilder); 1651 casesBuilder.jumpTo(join);
1652 } else {
1653 buildDefaultBody(casesBuilder);
1653 } 1654 }
1654 if (casesBuilder.isOpen) casesBuilder.jumpTo(join);
1655
1656 casesBuilder.state.breakCollectors.removeLast();
1657 1655
1658 if (!join.isEmpty) { 1656 if (!join.isEmpty) {
1659 add(new ir.LetCont(join.continuation, casesBuilder._root)); 1657 add(new ir.LetCont(join.continuation, casesBuilder.root));
1660 environment = join.environment; 1658 environment = join.environment;
1661 } else if (casesBuilder._root != null) { 1659 } else if (casesBuilder.root != null) {
1662 add(casesBuilder._root); 1660 add(casesBuilder.root);
1663 _current = casesBuilder._current; 1661 _current = casesBuilder._current;
1664 environment = casesBuilder.environment; 1662 environment = casesBuilder.environment;
1665 } else { 1663 } else {
1666 // The translation of the cases did not emit any code. 1664 // The translation of the cases did not emit any code.
1667 } 1665 }
1668 } 1666 }
1669 1667
1670 /// Utility function to translate try/catch into the IR. 1668 /// Utility function to translate try/catch into the IR.
1671 /// 1669 ///
1672 /// The translation treats try/finally and try/catch/finally as if they 1670 /// The translation treats try/finally and try/catch/finally as if they
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1714 assert(catchBuilder.isInMutableVariable(variable)); 1712 assert(catchBuilder.isInMutableVariable(variable));
1715 ir.Primitive value = catchBuilder.buildLocalGet(variable); 1713 ir.Primitive value = catchBuilder.buildLocalGet(variable);
1716 // After this point, the variables that were boxed on entry to the try 1714 // After this point, the variables that were boxed on entry to the try
1717 // are no longer treated as mutable. 1715 // are no longer treated as mutable.
1718 catchBuilder.removeMutableVariable(variable); 1716 catchBuilder.removeMutableVariable(variable);
1719 catchBuilder.environment.update(variable, value); 1717 catchBuilder.environment.update(variable, value);
1720 } 1718 }
1721 1719
1722 List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join); 1720 List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join);
1723 ir.Continuation catchContinuation = new ir.Continuation(catchParameters); 1721 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1724 catchContinuation.body = catchBuilder._root; 1722 catchContinuation.body = catchBuilder.root;
1725 tryCatchBuilder.add( 1723 tryCatchBuilder.add(
1726 new ir.LetHandler(catchContinuation, tryBuilder._root)); 1724 new ir.LetHandler(catchContinuation, tryBuilder.root));
1727 1725
1728 leaveTryCatch(this, join, tryCatchBuilder._root); 1726 leaveTryCatch(this, join, tryCatchBuilder.root);
1729 } 1727 }
1730 1728
1731 /// Translates a try/catch. 1729 /// Translates a try/catch.
1732 /// 1730 ///
1733 /// [variables] provides information on local variables declared and boxed 1731 /// [variables] provides information on local variables declared and boxed
1734 /// within the try body. 1732 /// within the try body.
1735 /// [buildTryBlock] builds the try block. 1733 /// [buildTryBlock] builds the try block.
1736 /// [catchClauseInfos] provides access to the catch type, exception variable, 1734 /// [catchClauseInfos] provides access to the catch type, exception variable,
1737 /// and stack trace variable, and a function for building the catch block. 1735 /// and stack trace variable, and a function for building the catch block.
1738 void buildTryCatch(TryStatementInfo variables, 1736 void buildTryCatch(TryStatementInfo variables,
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1822 if (clause.exceptionVariable != null) { 1820 if (clause.exceptionVariable != null) {
1823 clauseBuilder.declareLocalVariable(clause.exceptionVariable, 1821 clauseBuilder.declareLocalVariable(clause.exceptionVariable,
1824 initialValue: exceptionParameter); 1822 initialValue: exceptionParameter);
1825 } 1823 }
1826 if (clause.stackTraceVariable != null) { 1824 if (clause.stackTraceVariable != null) {
1827 clauseBuilder.declareLocalVariable(clause.stackTraceVariable, 1825 clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
1828 initialValue: traceParameter); 1826 initialValue: traceParameter);
1829 } 1827 }
1830 clause.buildCatchBlock(clauseBuilder); 1828 clause.buildCatchBlock(clauseBuilder);
1831 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join); 1829 if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
1832 return clauseBuilder._root; 1830 return clauseBuilder.root;
1833 } 1831 }
1834 1832
1835 // Expand multiple catch clauses into an explicit if/then/else. Iterate 1833 // Expand multiple catch clauses into an explicit if/then/else. Iterate
1836 // them in reverse so the current block becomes the next else block. 1834 // them in reverse so the current block becomes the next else block.
1837 ir.Expression catchBody = (catchAll == null) 1835 ir.Expression catchBody = (catchAll == null)
1838 ? new ir.Rethrow() 1836 ? new ir.Rethrow()
1839 : buildCatchClause(catchAll); 1837 : buildCatchClause(catchAll);
1840 for (CatchClauseInfo clause in catchClauseInfos.reversed) { 1838 for (CatchClauseInfo clause in catchClauseInfos.reversed) {
1841 ir.Continuation thenContinuation = new ir.Continuation([]); 1839 ir.Continuation thenContinuation = new ir.Continuation([]);
1842 ir.Continuation elseContinuation = new ir.Continuation([]); 1840 ir.Continuation elseContinuation = new ir.Continuation([]);
1843 thenContinuation.body = buildCatchClause(clause); 1841 thenContinuation.body = buildCatchClause(clause);
1844 elseContinuation.body = catchBody; 1842 elseContinuation.body = catchBody;
1845 1843
1846 // Build the type test guarding this clause. We can share the 1844 // Build the type test guarding this clause. We can share the
1847 // environment with the nested builder because this part cannot mutate 1845 // environment with the nested builder because this part cannot mutate
1848 // it. 1846 // it.
1849 IrBuilder checkBuilder = builder.makeDelimitedBuilder(environment); 1847 IrBuilder checkBuilder = builder.makeDelimitedBuilder(environment);
1850 ir.Primitive typeMatches = 1848 ir.Primitive typeMatches =
1851 checkBuilder.buildTypeOperator(exceptionParameter, 1849 checkBuilder.buildTypeOperator(exceptionParameter,
1852 clause.type, 1850 clause.type,
1853 isTypeTest: true); 1851 isTypeTest: true);
1854 checkBuilder.add(new ir.LetCont.two(thenContinuation, elseContinuation, 1852 checkBuilder.add(new ir.LetCont.two(thenContinuation, elseContinuation,
1855 new ir.Branch.strict(typeMatches, 1853 new ir.Branch.strict(typeMatches,
1856 thenContinuation, 1854 thenContinuation,
1857 elseContinuation))); 1855 elseContinuation)));
1858 catchBody = checkBuilder._root; 1856 catchBody = checkBuilder.root;
1859 } 1857 }
1860 builder.add(catchBody); 1858 builder.add(catchBody);
1861 1859
1862 return <ir.Parameter>[exceptionParameter, traceParameter]; 1860 return <ir.Parameter>[exceptionParameter, traceParameter];
1863 } 1861 }
1864 1862
1865 void leaveTryCatch(IrBuilder builder, JumpCollector join, 1863 void leaveTryCatch(IrBuilder builder, JumpCollector join,
1866 ir.Expression body) { 1864 ir.Expression body) {
1867 // Add the binding for the join-point continuation and continue the 1865 // Add the binding for the join-point continuation and continue the
1868 // translation in its body. 1866 // translation in its body.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1953 ir.Expression body) { 1951 ir.Expression body) {
1954 // Build a list of continuations for jumps from the try block and 1952 // Build a list of continuations for jumps from the try block and
1955 // duplicate the finally code before jumping to the actual target. 1953 // duplicate the finally code before jumping to the actual target.
1956 List<ir.Continuation> exits = <ir.Continuation>[join.continuation]; 1954 List<ir.Continuation> exits = <ir.Continuation>[join.continuation];
1957 void addJump(JumpCollector newCollector, 1955 void addJump(JumpCollector newCollector,
1958 JumpCollector originalCollector) { 1956 JumpCollector originalCollector) {
1959 if (newCollector.isEmpty) return; 1957 if (newCollector.isEmpty) return;
1960 IrBuilder builder = makeDelimitedBuilder(newCollector.environment); 1958 IrBuilder builder = makeDelimitedBuilder(newCollector.environment);
1961 buildFinallyBlock(builder); 1959 buildFinallyBlock(builder);
1962 if (builder.isOpen) builder.jumpTo(originalCollector); 1960 if (builder.isOpen) builder.jumpTo(originalCollector);
1963 newCollector.continuation.body = builder._root; 1961 newCollector.continuation.body = builder.root;
1964 exits.add(newCollector.continuation); 1962 exits.add(newCollector.continuation);
1965 } 1963 }
1966 for (int i = 0; i < newBreaks.length; ++i) { 1964 for (int i = 0; i < newBreaks.length; ++i) {
1967 addJump(newBreaks[i], savedBreaks[i]); 1965 addJump(newBreaks[i], savedBreaks[i]);
1968 } 1966 }
1969 for (int i = 0; i < newContinues.length; ++i) { 1967 for (int i = 0; i < newContinues.length; ++i) {
1970 addJump(newContinues[i], savedContinues[i]); 1968 addJump(newContinues[i], savedContinues[i]);
1971 } 1969 }
1972 if (!newReturn.isEmpty) { 1970 if (!newReturn.isEmpty) {
1973 IrBuilder builder = makeDelimitedBuilder(newReturn.environment); 1971 IrBuilder builder = makeDelimitedBuilder(newReturn.environment);
1974 ir.Primitive value = builder.environment.discard(1); 1972 ir.Primitive value = builder.environment.discard(1);
1975 buildFinallyBlock(builder); 1973 buildFinallyBlock(builder);
1976 if (builder.isOpen) builder.buildReturn(value: value); 1974 if (builder.isOpen) builder.buildReturn(value: value);
1977 newReturn.continuation.body = builder._root; 1975 newReturn.continuation.body = builder.root;
1978 exits.add(newReturn.continuation); 1976 exits.add(newReturn.continuation);
1979 } 1977 }
1980 builder.add(new ir.LetCont.many(exits, body)); 1978 builder.add(new ir.LetCont.many(exits, body));
1981 builder.environment = join.environment; 1979 builder.environment = join.environment;
1982 buildFinallyBlock(builder); 1980 buildFinallyBlock(builder);
1983 } 1981 }
1984 1982
1985 _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry, 1983 _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry,
1986 buildCatch, leaveTryCatch); 1984 buildCatch, leaveTryCatch);
1987 } 1985 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2094 void buildLabeledStatement({SubbuildFunction buildBody, 2092 void buildLabeledStatement({SubbuildFunction buildBody,
2095 JumpTarget target}) { 2093 JumpTarget target}) {
2096 JumpCollector join = new ForwardJumpCollector(environment, target: target); 2094 JumpCollector join = new ForwardJumpCollector(environment, target: target);
2097 IrBuilder innerBuilder = makeDelimitedBuilder(); 2095 IrBuilder innerBuilder = makeDelimitedBuilder();
2098 innerBuilder.state.breakCollectors.add(join); 2096 innerBuilder.state.breakCollectors.add(join);
2099 buildBody(innerBuilder); 2097 buildBody(innerBuilder);
2100 innerBuilder.state.breakCollectors.removeLast(); 2098 innerBuilder.state.breakCollectors.removeLast();
2101 bool hasBreaks = !join.isEmpty; 2099 bool hasBreaks = !join.isEmpty;
2102 if (hasBreaks) { 2100 if (hasBreaks) {
2103 if (innerBuilder.isOpen) innerBuilder.jumpTo(join); 2101 if (innerBuilder.isOpen) innerBuilder.jumpTo(join);
2104 add(new ir.LetCont(join.continuation, innerBuilder._root)); 2102 add(new ir.LetCont(join.continuation, innerBuilder.root));
2105 environment = join.environment; 2103 environment = join.environment;
2106 } else if (innerBuilder._root != null) { 2104 } else if (innerBuilder.root != null) {
2107 add(innerBuilder._root); 2105 add(innerBuilder.root);
2108 _current = innerBuilder._current; 2106 _current = innerBuilder._current;
2109 environment = innerBuilder.environment; 2107 environment = innerBuilder.environment;
2110 } else { 2108 } else {
2111 // The translation of the body did not emit any CPS term. 2109 // The translation of the body did not emit any CPS term.
2112 } 2110 }
2113 } 2111 }
2114 2112
2115 // Build(BreakStatement L, C) = C[InvokeContinuation(...)] 2113 // Build(BreakStatement L, C) = C[InvokeContinuation(...)]
2116 // 2114 //
2117 // The continuation and arguments are filled in later after translating 2115 // The continuation and arguments are filled in later after translating
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
2233 // for the right subexpression, and a three-way join continuation. 2231 // for the right subexpression, and a three-way join continuation.
2234 JumpCollector join = 2232 JumpCollector join =
2235 new ForwardJumpCollector(environment, hasExtraArgument: true); 2233 new ForwardJumpCollector(environment, hasExtraArgument: true);
2236 emptyBuilder.jumpTo(join, leftBool); 2234 emptyBuilder.jumpTo(join, leftBool);
2237 rightTrueBuilder.jumpTo(join, rightTrue); 2235 rightTrueBuilder.jumpTo(join, rightTrue);
2238 rightFalseBuilder.jumpTo(join, rightFalse); 2236 rightFalseBuilder.jumpTo(join, rightFalse);
2239 ir.Continuation leftTrueContinuation = new ir.Continuation([]); 2237 ir.Continuation leftTrueContinuation = new ir.Continuation([]);
2240 ir.Continuation leftFalseContinuation = new ir.Continuation([]); 2238 ir.Continuation leftFalseContinuation = new ir.Continuation([]);
2241 ir.Continuation rightTrueContinuation = new ir.Continuation([]); 2239 ir.Continuation rightTrueContinuation = new ir.Continuation([]);
2242 ir.Continuation rightFalseContinuation = new ir.Continuation([]); 2240 ir.Continuation rightFalseContinuation = new ir.Continuation([]);
2243 rightTrueContinuation.body = rightTrueBuilder._root; 2241 rightTrueContinuation.body = rightTrueBuilder.root;
2244 rightFalseContinuation.body = rightFalseBuilder._root; 2242 rightFalseContinuation.body = rightFalseBuilder.root;
2245 // The right subexpression has two continuations. 2243 // The right subexpression has two continuations.
2246 rightBuilder.add( 2244 rightBuilder.add(
2247 new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation, 2245 new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation,
2248 new ir.Branch.strict(rightValue, 2246 new ir.Branch.strict(rightValue,
2249 rightTrueContinuation, 2247 rightTrueContinuation,
2250 rightFalseContinuation))); 2248 rightFalseContinuation)));
2251 // Depending on the operator, the left subexpression's continuations are 2249 // Depending on the operator, the left subexpression's continuations are
2252 // either the right subexpression or an invocation of the join-point 2250 // either the right subexpression or an invocation of the join-point
2253 // continuation. 2251 // continuation.
2254 if (isLazyOr) { 2252 if (isLazyOr) {
2255 leftTrueContinuation.body = emptyBuilder._root; 2253 leftTrueContinuation.body = emptyBuilder.root;
2256 leftFalseContinuation.body = rightBuilder._root; 2254 leftFalseContinuation.body = rightBuilder.root;
2257 } else { 2255 } else {
2258 leftTrueContinuation.body = rightBuilder._root; 2256 leftTrueContinuation.body = rightBuilder.root;
2259 leftFalseContinuation.body = emptyBuilder._root; 2257 leftFalseContinuation.body = emptyBuilder.root;
2260 } 2258 }
2261 2259
2262 add(new ir.LetCont(join.continuation, 2260 add(new ir.LetCont(join.continuation,
2263 new ir.LetCont.two(leftTrueContinuation, leftFalseContinuation, 2261 new ir.LetCont.two(leftTrueContinuation, leftFalseContinuation,
2264 new ir.Branch.strict(leftValue, 2262 new ir.Branch.strict(leftValue,
2265 leftTrueContinuation, 2263 leftTrueContinuation,
2266 leftFalseContinuation)))); 2264 leftFalseContinuation))));
2267 environment = join.environment; 2265 environment = join.environment;
2268 return environment.discard(1); 2266 return environment.discard(1);
2269 } 2267 }
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after
2831 final LocalVariableElement stackTraceVariable; 2829 final LocalVariableElement stackTraceVariable;
2832 final SubbuildFunction buildCatchBlock; 2830 final SubbuildFunction buildCatchBlock;
2833 2831
2834 CatchClauseInfo({this.type, 2832 CatchClauseInfo({this.type,
2835 this.exceptionVariable, 2833 this.exceptionVariable,
2836 this.stackTraceVariable, 2834 this.stackTraceVariable,
2837 this.buildCatchBlock}); 2835 this.buildCatchBlock});
2838 } 2836 }
2839 2837
2840 class SwitchCaseInfo { 2838 class SwitchCaseInfo {
2841 final List<ir.Primitive> constants = <ir.Primitive>[]; 2839 final SubbuildFunction buildCondition;
2842 final SubbuildFunction buildBody; 2840 final SubbuildFunction buildBody;
2843 2841
2844 SwitchCaseInfo(this.buildBody); 2842 SwitchCaseInfo(this.buildCondition, this.buildBody);
2845
2846 void addConstant(ir.Primitive constant) => constants.add(constant);
2847 } 2843 }
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