| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |