| 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 '../constants/expressions.dart'; | 7 import '../constants/expressions.dart'; |
| 8 import '../constants/values.dart' show PrimitiveConstantValue; | 8 import '../constants/values.dart' show PrimitiveConstantValue; |
| 9 import '../dart_backend/dart_backend.dart' show DartBackend; | 9 import '../dart_backend/dart_backend.dart' show DartBackend; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 environment = condBuilder.environment; | 770 environment = condBuilder.environment; |
| 771 breakCollector.addJump(this); | 771 breakCollector.addJump(this); |
| 772 letJoin.continuation = createJoin(environment.length, breakCollector); | 772 letJoin.continuation = createJoin(environment.length, breakCollector); |
| 773 _current = letJoin; | 773 _current = letJoin; |
| 774 } else { | 774 } else { |
| 775 _current = condBuilder._current; | 775 _current = condBuilder._current; |
| 776 environment = condBuilder.environment; | 776 environment = condBuilder.environment; |
| 777 } | 777 } |
| 778 } | 778 } |
| 779 | 779 |
| 780 |
| 781 /// Creates a while loop in which the condition and body are created by |
| 782 /// [buildCondition] and [buildBody], respectively. |
| 783 /// |
| 784 /// The jump [target] is used to identify which `break` and `continue` |
| 785 /// statements that have this `while` statement as their target. |
| 786 void buildWhile({SubbuildFunction buildCondition, |
| 787 SubbuildFunction buildBody, |
| 788 JumpTarget target}) { |
| 789 assert(isOpen); |
| 790 // While loops use four named continuations: the entry to the body, the |
| 791 // loop exit, the loop back edge (continue), and the loop exit (break). |
| 792 // The CPS translation of [[while (condition) body; successor]] is: |
| 793 // |
| 794 // let cont continue(x, ...) = |
| 795 // let prim cond = [[condition]] in |
| 796 // let cont break() = [[successor]] in |
| 797 // let cont exit() = break(v, ...) in |
| 798 // let cont body() = [[body]]; continue(v, ...) in |
| 799 // branch cond (body, exit) in |
| 800 // continue(v, ...) |
| 801 // |
| 802 // If there are no breaks in the body, the break continuation is inlined |
| 803 // in the exit continuation (i.e., the translation of the successor |
| 804 // statement occurs in the exit continuation). |
| 805 |
| 806 // The condition and body are delimited. |
| 807 IrBuilder condBuilder = new IrBuilder.recursive(this); |
| 808 ir.Primitive condition = buildCondition(condBuilder); |
| 809 |
| 810 JumpCollector breakCollector = new JumpCollector(target); |
| 811 JumpCollector continueCollector = new JumpCollector(target); |
| 812 state.breakCollectors.add(breakCollector); |
| 813 state.continueCollectors.add(continueCollector); |
| 814 |
| 815 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder); |
| 816 buildBody(bodyBuilder); |
| 817 assert(state.breakCollectors.last == breakCollector); |
| 818 assert(state.continueCollectors.last == continueCollector); |
| 819 state.breakCollectors.removeLast(); |
| 820 state.continueCollectors.removeLast(); |
| 821 |
| 822 // Create body entry and loop exit continuations and a branch to them. |
| 823 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 824 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 825 ir.LetCont branch = |
| 826 new ir.LetCont(exitContinuation, |
| 827 new ir.LetCont(bodyContinuation, |
| 828 new ir.Branch(new ir.IsTrue(condition), |
| 829 bodyContinuation, |
| 830 exitContinuation))); |
| 831 // If there are breaks in the body, then there must be a join-point |
| 832 // continuation for the normal exit and the breaks. |
| 833 bool hasBreaks = !breakCollector.isEmpty; |
| 834 ir.LetCont letJoin; |
| 835 if (hasBreaks) { |
| 836 letJoin = new ir.LetCont(null, branch); |
| 837 condBuilder.add(letJoin); |
| 838 condBuilder._current = branch; |
| 839 } else { |
| 840 condBuilder.add(branch); |
| 841 } |
| 842 ir.Continuation loopContinuation = |
| 843 new ir.Continuation(condBuilder._parameters); |
| 844 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); |
| 845 invokeFullJoin(loopContinuation, continueCollector, recursive: true); |
| 846 bodyContinuation.body = bodyBuilder._root; |
| 847 |
| 848 loopContinuation.body = condBuilder._root; |
| 849 add(new ir.LetCont(loopContinuation, |
| 850 new ir.InvokeContinuation(loopContinuation, |
| 851 environment.index2value))); |
| 852 if (hasBreaks) { |
| 853 _current = branch; |
| 854 environment = condBuilder.environment; |
| 855 breakCollector.addJump(this); |
| 856 letJoin.continuation = createJoin(environment.length, breakCollector); |
| 857 _current = letJoin; |
| 858 } else { |
| 859 _current = condBuilder._current; |
| 860 environment = condBuilder.environment; |
| 861 } |
| 862 } |
| 863 |
| 780 /// Create a return statement `return value;` or `return;` if [value] is | 864 /// Create a return statement `return value;` or `return;` if [value] is |
| 781 /// null. | 865 /// null. |
| 782 void buildReturn([ir.Primitive value]) { | 866 void buildReturn([ir.Primitive value]) { |
| 783 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] | 867 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] |
| 784 // where (C', x) = Build(e, C) | 868 // where (C', x) = Build(e, C) |
| 785 // | 869 // |
| 786 // Return without a subexpression is translated as if it were return null. | 870 // Return without a subexpression is translated as if it were return null. |
| 787 assert(isOpen); | 871 assert(isOpen); |
| 788 if (value == null) { | 872 if (value == null) { |
| 789 value = buildNullLiteral(); | 873 value = buildNullLiteral(); |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 index = 0; | 1144 index = 0; |
| 1061 for (int i = 0; i < environment.length; ++i) { | 1145 for (int i = 0; i < environment.length; ++i) { |
| 1062 if (common[i] == null) { | 1146 if (common[i] == null) { |
| 1063 environment.index2value[i] = parameters[index++]; | 1147 environment.index2value[i] = parameters[index++]; |
| 1064 } | 1148 } |
| 1065 } | 1149 } |
| 1066 | 1150 |
| 1067 return join; | 1151 return join; |
| 1068 } | 1152 } |
| 1069 } | 1153 } |
| OLD | NEW |