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 866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 environment = condBuilder.environment; | 877 environment = condBuilder.environment; |
878 breakCollector.addJump(this); | 878 breakCollector.addJump(this); |
879 letJoin.continuation = createJoin(environment.length, breakCollector); | 879 letJoin.continuation = createJoin(environment.length, breakCollector); |
880 _current = letJoin; | 880 _current = letJoin; |
881 } else { | 881 } else { |
882 _current = condBuilder._current; | 882 _current = condBuilder._current; |
883 environment = condBuilder.environment; | 883 environment = condBuilder.environment; |
884 } | 884 } |
885 } | 885 } |
886 | 886 |
| 887 /// Creates a for-in loop, `for (v in e) b`. |
| 888 /// |
| 889 /// [buildExpression] creates the expression, `e`. The variable, `v`, can |
| 890 /// take one of three forms: |
| 891 /// 1) `v` can be declared within the for-in statement, like in |
| 892 /// `for (var v in e)`, in which case, [buildVariableDeclaration] |
| 893 /// creates its declaration and [variableElement] is the element for |
| 894 /// the declared variable, |
| 895 /// 2) `v` is predeclared statically known variable, that is top-level, |
| 896 /// static, or local variable, in which case [variableElement] is the |
| 897 /// variable element, and [variableSelector] defines its write access, |
| 898 /// 3) `v` is an instance variable in which case [variableSelector] |
| 899 /// defines its write access. |
| 900 /// [buildBody] creates the body, `b`, of the loop. The jump [target] is used |
| 901 /// to identify which `break` and `continue` statements that have this for-in |
| 902 /// statement as their target. |
| 903 void buildForIn({SubbuildFunction buildExpression, |
| 904 SubbuildFunction buildVariableDeclaration, |
| 905 Element variableElement, |
| 906 Selector variableSelector, |
| 907 SubbuildFunction buildBody, |
| 908 JumpTarget target}) { |
| 909 // The for-in loop |
| 910 // |
| 911 // for (a in e) s; |
| 912 // |
| 913 // Is compiled analogously to: |
| 914 // |
| 915 // a = e.iterator; |
| 916 // while (a.moveNext()) { |
| 917 // var n0 = a.current; |
| 918 // s; |
| 919 // } |
| 920 |
| 921 // The condition and body are delimited. |
| 922 IrBuilder condBuilder = new IrBuilder.recursive(this); |
| 923 |
| 924 ir.Primitive expressionReceiver = buildExpression(this); |
| 925 List<ir.Primitive> emptyArguments = new List<ir.Primitive>(); |
| 926 |
| 927 ir.Parameter iterator = new ir.Parameter(null); |
| 928 ir.Continuation iteratorInvoked = new ir.Continuation([iterator]); |
| 929 add(new ir.LetCont(iteratorInvoked, |
| 930 new ir.InvokeMethod(expressionReceiver, |
| 931 new Selector.getter("iterator", null), iteratorInvoked, |
| 932 emptyArguments))); |
| 933 |
| 934 ir.Parameter condition = new ir.Parameter(null); |
| 935 ir.Continuation moveNextInvoked = new ir.Continuation([condition]); |
| 936 condBuilder.add(new ir.LetCont(moveNextInvoked, |
| 937 new ir.InvokeMethod(iterator, |
| 938 new Selector.call("moveNext", null, 0), |
| 939 moveNextInvoked, emptyArguments))); |
| 940 |
| 941 JumpCollector breakCollector = new JumpCollector(target); |
| 942 JumpCollector continueCollector = new JumpCollector(target); |
| 943 state.breakCollectors.add(breakCollector); |
| 944 state.continueCollectors.add(continueCollector); |
| 945 |
| 946 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder); |
| 947 if (buildVariableDeclaration != null) { |
| 948 buildVariableDeclaration(bodyBuilder); |
| 949 } |
| 950 |
| 951 ir.Parameter currentValue = new ir.Parameter(null); |
| 952 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); |
| 953 bodyBuilder.add(new ir.LetCont(currentInvoked, |
| 954 new ir.InvokeMethod(iterator, new Selector.getter("current", null), |
| 955 currentInvoked, emptyArguments))); |
| 956 if (Elements.isLocal(variableElement)) { |
| 957 bodyBuilder.buildLocalSet(variableElement, currentValue); |
| 958 } else if (Elements.isStaticOrTopLevel(variableElement)) { |
| 959 bodyBuilder.buildStaticSet( |
| 960 variableElement, variableSelector, currentValue); |
| 961 } else { |
| 962 ir.Primitive receiver = bodyBuilder.buildThis(); |
| 963 bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue); |
| 964 } |
| 965 |
| 966 buildBody(bodyBuilder); |
| 967 assert(state.breakCollectors.last == breakCollector); |
| 968 assert(state.continueCollectors.last == continueCollector); |
| 969 state.breakCollectors.removeLast(); |
| 970 state.continueCollectors.removeLast(); |
| 971 |
| 972 // Create body entry and loop exit continuations and a branch to them. |
| 973 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 974 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 975 ir.LetCont branch = |
| 976 new ir.LetCont(exitContinuation, |
| 977 new ir.LetCont(bodyContinuation, |
| 978 new ir.Branch(new ir.IsTrue(condition), |
| 979 bodyContinuation, |
| 980 exitContinuation))); |
| 981 // If there are breaks in the body, then there must be a join-point |
| 982 // continuation for the normal exit and the breaks. |
| 983 bool hasBreaks = !breakCollector.isEmpty; |
| 984 ir.LetCont letJoin; |
| 985 if (hasBreaks) { |
| 986 letJoin = new ir.LetCont(null, branch); |
| 987 condBuilder.add(letJoin); |
| 988 condBuilder._current = branch; |
| 989 } else { |
| 990 condBuilder.add(branch); |
| 991 } |
| 992 ir.Continuation loopContinuation = |
| 993 new ir.Continuation(condBuilder._parameters); |
| 994 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); |
| 995 invokeFullJoin( |
| 996 loopContinuation, continueCollector, recursive: true); |
| 997 bodyContinuation.body = bodyBuilder._root; |
| 998 |
| 999 loopContinuation.body = condBuilder._root; |
| 1000 add(new ir.LetCont(loopContinuation, |
| 1001 new ir.InvokeContinuation(loopContinuation, |
| 1002 environment.index2value))); |
| 1003 if (hasBreaks) { |
| 1004 _current = branch; |
| 1005 environment = condBuilder.environment; |
| 1006 breakCollector.addJump(this); |
| 1007 letJoin.continuation = createJoin(environment.length, breakCollector); |
| 1008 _current = letJoin; |
| 1009 } else { |
| 1010 _current = condBuilder._current; |
| 1011 environment = condBuilder.environment; |
| 1012 } |
| 1013 } |
887 | 1014 |
888 /// Creates a while loop in which the condition and body are created by | 1015 /// Creates a while loop in which the condition and body are created by |
889 /// [buildCondition] and [buildBody], respectively. | 1016 /// [buildCondition] and [buildBody], respectively. |
890 /// | 1017 /// |
891 /// The jump [target] is used to identify which `break` and `continue` | 1018 /// The jump [target] is used to identify which `break` and `continue` |
892 /// statements that have this `while` statement as their target. | 1019 /// statements that have this `while` statement as their target. |
893 void buildWhile({SubbuildFunction buildCondition, | 1020 void buildWhile({SubbuildFunction buildCondition, |
894 SubbuildFunction buildBody, | 1021 SubbuildFunction buildBody, |
895 JumpTarget target}) { | 1022 JumpTarget target}) { |
896 assert(isOpen); | 1023 assert(isOpen); |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1163 new ir.LetCont(leftTrueContinuation, | 1290 new ir.LetCont(leftTrueContinuation, |
1164 new ir.LetCont(leftFalseContinuation, | 1291 new ir.LetCont(leftFalseContinuation, |
1165 new ir.Branch(new ir.IsTrue(leftValue), | 1292 new ir.Branch(new ir.IsTrue(leftValue), |
1166 leftTrueContinuation, | 1293 leftTrueContinuation, |
1167 leftFalseContinuation))))); | 1294 leftFalseContinuation))))); |
1168 // There is always a join parameter for the result value, because it | 1295 // There is always a join parameter for the result value, because it |
1169 // is different on at least two paths. | 1296 // is different on at least two paths. |
1170 return joinContinuation.parameters.last; | 1297 return joinContinuation.parameters.last; |
1171 } | 1298 } |
1172 | 1299 |
| 1300 /// Creates an access to `this`. |
| 1301 ir.Primitive buildThis() { |
| 1302 assert(isOpen); |
| 1303 ir.Primitive result = new ir.This(); |
| 1304 add(new ir.LetPrim(result)); |
| 1305 return result; |
| 1306 } |
| 1307 |
1173 /// Create a non-recursive join-point continuation. | 1308 /// Create a non-recursive join-point continuation. |
1174 /// | 1309 /// |
1175 /// Given the environment length at the join point and a list of | 1310 /// Given the environment length at the join point and a list of |
1176 /// jumps that should reach the join point, create a join-point | 1311 /// jumps that should reach the join point, create a join-point |
1177 /// continuation. The join-point continuation has a parameter for each | 1312 /// continuation. The join-point continuation has a parameter for each |
1178 /// variable that has different values reaching on different paths. | 1313 /// variable that has different values reaching on different paths. |
1179 /// | 1314 /// |
1180 /// The jumps are uninitialized [ir.InvokeContinuation] expressions. | 1315 /// The jumps are uninitialized [ir.InvokeContinuation] expressions. |
1181 /// They are filled in with the target continuation and appropriate | 1316 /// They are filled in with the target continuation and appropriate |
1182 /// arguments. | 1317 /// arguments. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 index = 0; | 1403 index = 0; |
1269 for (int i = 0; i < environment.length; ++i) { | 1404 for (int i = 0; i < environment.length; ++i) { |
1270 if (common[i] == null) { | 1405 if (common[i] == null) { |
1271 environment.index2value[i] = parameters[index++]; | 1406 environment.index2value[i] = parameters[index++]; |
1272 } | 1407 } |
1273 } | 1408 } |
1274 | 1409 |
1275 return join; | 1410 return join; |
1276 } | 1411 } |
1277 } | 1412 } |
OLD | NEW |