| 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_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../dart2jslib.dart'; | 10 import '../dart2jslib.dart'; |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 _root = _current = expr; | 381 _root = _current = expr; |
| 382 } else { | 382 } else { |
| 383 _current = _current.plug(expr); | 383 _current = _current.plug(expr); |
| 384 } | 384 } |
| 385 } | 385 } |
| 386 | 386 |
| 387 ir.Primitive _continueWithExpression(ir.Expression build(ir.Continuation k)) { | 387 ir.Primitive _continueWithExpression(ir.Expression build(ir.Continuation k)) { |
| 388 ir.Parameter v = new ir.Parameter(null); | 388 ir.Parameter v = new ir.Parameter(null); |
| 389 ir.Continuation k = new ir.Continuation([v]); | 389 ir.Continuation k = new ir.Continuation([v]); |
| 390 ir.Expression expression = build(k); | 390 ir.Expression expression = build(k); |
| 391 add(new ir.LetCont(k, expression)); | 391 add(new ir.LetCont(<ir.Continuation>[k], expression)); |
| 392 return v; | 392 return v; |
| 393 } | 393 } |
| 394 | 394 |
| 395 ir.Primitive _buildInvokeStatic(Element element, | 395 ir.Primitive _buildInvokeStatic(Element element, |
| 396 Selector selector, | 396 Selector selector, |
| 397 List<ir.Primitive> arguments) { | 397 List<ir.Primitive> arguments) { |
| 398 assert(isOpen); | 398 assert(isOpen); |
| 399 return _continueWithExpression( | 399 return _continueWithExpression( |
| 400 (k) => new ir.InvokeStatic(element, selector, k, arguments)); | 400 (k) => new ir.InvokeStatic(element, selector, k, arguments)); |
| 401 } | 401 } |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 | 525 |
| 526 // Build the term | 526 // Build the term |
| 527 // let cont join(x, ..., result) = [] in | 527 // let cont join(x, ..., result) = [] in |
| 528 // let cont then() = [[thenPart]]; join(v, ...) in | 528 // let cont then() = [[thenPart]]; join(v, ...) in |
| 529 // let cont else() = [[elsePart]]; join(v, ...) in | 529 // let cont else() = [[elsePart]]; join(v, ...) in |
| 530 // if condition (then, else) | 530 // if condition (then, else) |
| 531 ir.Continuation thenContinuation = new ir.Continuation([]); | 531 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 532 ir.Continuation elseContinuation = new ir.Continuation([]); | 532 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 533 thenContinuation.body = thenBuilder._root; | 533 thenContinuation.body = thenBuilder._root; |
| 534 elseContinuation.body = elseBuilder._root; | 534 elseContinuation.body = elseBuilder._root; |
| 535 add(new ir.LetCont(joinContinuation, | 535 add(new ir.LetCont(<ir.Continuation>[joinContinuation], |
| 536 new ir.LetCont(thenContinuation, | 536 new ir.LetCont(<ir.Continuation>[thenContinuation, |
| 537 new ir.LetCont(elseContinuation, | 537 elseContinuation], |
| 538 new ir.Branch(new ir.IsTrue(condition), | 538 new ir.Branch(new ir.IsTrue(condition), |
| 539 thenContinuation, | 539 thenContinuation, |
| 540 elseContinuation))))); | 540 elseContinuation)))); |
| 541 return (thenValue == elseValue) | 541 return (thenValue == elseValue) |
| 542 ? thenValue | 542 ? thenValue |
| 543 : joinContinuation.parameters.last; | 543 : joinContinuation.parameters.last; |
| 544 | |
| 545 } | 544 } |
| 546 | 545 |
| 547 /** | 546 /** |
| 548 * Add an explicit `return null` for functions that don't have a return | 547 * Add an explicit `return null` for functions that don't have a return |
| 549 * statement on each branch. This includes functions with an empty body, | 548 * statement on each branch. This includes functions with an empty body, |
| 550 * such as `foo(){ }`. | 549 * such as `foo(){ }`. |
| 551 */ | 550 */ |
| 552 void _ensureReturn() { | 551 void _ensureReturn() { |
| 553 if (!isOpen) return; | 552 if (!isOpen) return; |
| 554 ir.Constant constant = buildNullLiteral(); | 553 ir.Constant constant = buildNullLiteral(); |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 IrBuilder elseBuilder = makeDelimitedBuilder(); | 777 IrBuilder elseBuilder = makeDelimitedBuilder(); |
| 779 buildThenPart(thenBuilder); | 778 buildThenPart(thenBuilder); |
| 780 buildElsePart(elseBuilder); | 779 buildElsePart(elseBuilder); |
| 781 | 780 |
| 782 // Build the term | 781 // Build the term |
| 783 // (Result =) let cont then() = [[thenPart]] in | 782 // (Result =) let cont then() = [[thenPart]] in |
| 784 // let cont else() = [[elsePart]] in | 783 // let cont else() = [[elsePart]] in |
| 785 // if condition (then, else) | 784 // if condition (then, else) |
| 786 ir.Continuation thenContinuation = new ir.Continuation([]); | 785 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 787 ir.Continuation elseContinuation = new ir.Continuation([]); | 786 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 788 ir.Expression letElse = | 787 // If exactly one of the then and else continuation bodies is open (i.e., |
| 789 new ir.LetCont(elseContinuation, | 788 // the other one has an exit on all paths), then Continuation.plug expects |
| 790 new ir.Branch(new ir.IsTrue(condition), | 789 // that continuation to be listed first. Arbitrarily use [then, else] |
| 791 thenContinuation, | 790 // order otherwise. |
| 792 elseContinuation)); | 791 List<ir.Continuation> arms = !thenBuilder.isOpen && elseBuilder.isOpen |
| 793 ir.Expression letThen = new ir.LetCont(thenContinuation, letElse); | 792 ? <ir.Continuation>[elseContinuation, thenContinuation] |
| 794 ir.Expression result = letThen; | 793 : <ir.Continuation>[thenContinuation, elseContinuation]; |
| 794 |
| 795 ir.Expression result = |
| 796 new ir.LetCont(arms, |
| 797 new ir.Branch(new ir.IsTrue(condition), |
| 798 thenContinuation, |
| 799 elseContinuation)); |
| 795 | 800 |
| 796 ir.Continuation joinContinuation; // Null if there is no join. | 801 ir.Continuation joinContinuation; // Null if there is no join. |
| 797 if (thenBuilder.isOpen && elseBuilder.isOpen) { | 802 if (thenBuilder.isOpen && elseBuilder.isOpen) { |
| 798 // There is a join-point continuation. Build the term | 803 // There is a join-point continuation. Build the term |
| 799 // 'let cont join(x, ...) = [] in Result' and plug invocations of the | 804 // 'let cont join(x, ...) = [] in Result' and plug invocations of the |
| 800 // join-point continuation into the then and else continuations. | 805 // join-point continuation into the then and else continuations. |
| 801 JumpCollector jumps = new JumpCollector(null); | 806 JumpCollector jumps = new JumpCollector(null); |
| 802 jumps.addJump(thenBuilder); | 807 jumps.addJump(thenBuilder); |
| 803 jumps.addJump(elseBuilder); | 808 jumps.addJump(elseBuilder); |
| 804 joinContinuation = createJoin(environment.length, jumps); | 809 joinContinuation = createJoin(environment.length, jumps); |
| 805 result = new ir.LetCont(joinContinuation, result); | 810 result = new ir.LetCont(<ir.Continuation>[joinContinuation], result); |
| 806 } | 811 } |
| 807 | 812 |
| 808 // The then or else term root could be null, but not both. If there is | 813 // The then or else term root could be null, but not both. If there is |
| 809 // a join then an InvokeContinuation was just added to both of them. If | 814 // a join then an InvokeContinuation was just added to both of them. If |
| 810 // there is no join, then at least one of them is closed and thus has a | 815 // there is no join, then at least one of them is closed and thus has a |
| 811 // non-null root by the definition of the predicate isClosed. In the | 816 // non-null root by the definition of the predicate isClosed. In the |
| 812 // case that one of them is null, it must be the only one that is open | 817 // case that one of them is null, it must be the only one that is open |
| 813 // and thus contains the new hole in the context. This case is handled | 818 // and thus contains the new hole in the context. This case is handled |
| 814 // after the branch is plugged into the current hole. | 819 // after the branch is plugged into the current hole. |
| 815 thenContinuation.body = thenBuilder._root; | 820 thenContinuation.body = thenBuilder._root; |
| 816 elseContinuation.body = elseBuilder._root; | 821 elseContinuation.body = elseBuilder._root; |
| 817 | 822 |
| 818 add(result); | 823 add(result); |
| 819 if (joinContinuation == null) { | 824 if (joinContinuation == null) { |
| 820 // At least one subexpression is closed. | 825 // At least one subexpression is closed. |
| 821 if (thenBuilder.isOpen) { | 826 if (thenBuilder.isOpen) { |
| 822 _current = | 827 if (thenBuilder._root != null) _current = thenBuilder._current; |
| 823 (thenBuilder._root == null) ? letThen : thenBuilder._current; | |
| 824 environment = thenBuilder.environment; | 828 environment = thenBuilder.environment; |
| 825 } else if (elseBuilder.isOpen) { | 829 } else if (elseBuilder.isOpen) { |
| 826 _current = | 830 if (elseBuilder._root != null) _current = elseBuilder._current; |
| 827 (elseBuilder._root == null) ? letElse : elseBuilder._current; | |
| 828 environment = elseBuilder.environment; | 831 environment = elseBuilder.environment; |
| 829 } else { | 832 } else { |
| 830 _current = null; | 833 _current = null; |
| 831 } | 834 } |
| 832 } | 835 } |
| 833 } | 836 } |
| 834 | 837 |
| 835 /// Invoke a join-point continuation that contains arguments for all local | 838 /// Invoke a join-point continuation that contains arguments for all local |
| 836 /// variables. | 839 /// variables. |
| 837 /// | 840 /// |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 bool hasContinues = !continueCollector.isEmpty; | 932 bool hasContinues = !continueCollector.isEmpty; |
| 930 IrBuilder updateBuilder = hasContinues | 933 IrBuilder updateBuilder = hasContinues |
| 931 ? condBuilder.makeRecursiveBuilder() | 934 ? condBuilder.makeRecursiveBuilder() |
| 932 : bodyBuilder; | 935 : bodyBuilder; |
| 933 updateBuilder._enterForLoopUpdate(closureScope, loopVariables); | 936 updateBuilder._enterForLoopUpdate(closureScope, loopVariables); |
| 934 buildUpdate(updateBuilder); | 937 buildUpdate(updateBuilder); |
| 935 | 938 |
| 936 // Create body entry and loop exit continuations and a branch to them. | 939 // Create body entry and loop exit continuations and a branch to them. |
| 937 ir.Continuation bodyContinuation = new ir.Continuation([]); | 940 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 938 ir.Continuation exitContinuation = new ir.Continuation([]); | 941 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 942 // Note the order of continuations: the first one is the one that will |
| 943 // be filled by LetCont.plug. |
| 939 ir.LetCont branch = | 944 ir.LetCont branch = |
| 940 new ir.LetCont(exitContinuation, | 945 new ir.LetCont(<ir.Continuation>[exitContinuation, bodyContinuation], |
| 941 new ir.LetCont(bodyContinuation, | 946 new ir.Branch(new ir.IsTrue(condition), |
| 942 new ir.Branch(new ir.IsTrue(condition), | 947 bodyContinuation, |
| 943 bodyContinuation, | 948 exitContinuation)); |
| 944 exitContinuation))); | |
| 945 // If there are breaks in the body, then there must be a join-point | 949 // If there are breaks in the body, then there must be a join-point |
| 946 // continuation for the normal exit and the breaks. | 950 // continuation for the normal exit and the breaks. |
| 947 bool hasBreaks = !breakCollector.isEmpty; | 951 bool hasBreaks = !breakCollector.isEmpty; |
| 948 ir.LetCont letJoin; | 952 ir.LetCont letJoin; |
| 949 if (hasBreaks) { | 953 if (hasBreaks) { |
| 950 letJoin = new ir.LetCont(null, branch); | 954 letJoin = new ir.LetCont(null, branch); |
| 951 condBuilder.add(letJoin); | 955 condBuilder.add(letJoin); |
| 952 condBuilder._current = branch; | 956 condBuilder._current = branch; |
| 953 } else { | 957 } else { |
| 954 condBuilder.add(branch); | 958 condBuilder.add(branch); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 967 JumpCollector backEdges = new JumpCollector(null); | 971 JumpCollector backEdges = new JumpCollector(null); |
| 968 backEdges.addJump(updateBuilder); | 972 backEdges.addJump(updateBuilder); |
| 969 invokeFullJoin(loopContinuation, backEdges, recursive: true); | 973 invokeFullJoin(loopContinuation, backEdges, recursive: true); |
| 970 } | 974 } |
| 971 | 975 |
| 972 // Fill in the body and possible continue continuation bodies. Do this | 976 // Fill in the body and possible continue continuation bodies. Do this |
| 973 // only after it is guaranteed that they are not empty. | 977 // only after it is guaranteed that they are not empty. |
| 974 if (hasContinues) { | 978 if (hasContinues) { |
| 975 continueContinuation.body = updateBuilder._root; | 979 continueContinuation.body = updateBuilder._root; |
| 976 bodyContinuation.body = | 980 bodyContinuation.body = |
| 977 new ir.LetCont(continueContinuation, bodyBuilder._root); | 981 new ir.LetCont(<ir.Continuation>[continueContinuation], |
| 982 bodyBuilder._root); |
| 978 } else { | 983 } else { |
| 979 bodyContinuation.body = bodyBuilder._root; | 984 bodyContinuation.body = bodyBuilder._root; |
| 980 } | 985 } |
| 981 | 986 |
| 982 loopContinuation.body = condBuilder._root; | 987 loopContinuation.body = condBuilder._root; |
| 983 add(new ir.LetCont(loopContinuation, | 988 add(new ir.LetCont(<ir.Continuation>[loopContinuation], |
| 984 new ir.InvokeContinuation(loopContinuation, | 989 new ir.InvokeContinuation(loopContinuation, |
| 985 environment.index2value))); | 990 environment.index2value))); |
| 986 if (hasBreaks) { | 991 if (hasBreaks) { |
| 987 _current = branch; | 992 _current = branch; |
| 988 environment = condBuilder.environment; | 993 environment = condBuilder.environment; |
| 989 breakCollector.addJump(this); | 994 breakCollector.addJump(this); |
| 990 letJoin.continuation = createJoin(environment.length, breakCollector); | 995 letJoin.continuations = |
| 996 <ir.Continuation>[createJoin(environment.length, breakCollector)]; |
| 991 _current = letJoin; | 997 _current = letJoin; |
| 992 } else { | 998 } else { |
| 993 _current = condBuilder._current; | 999 _current = condBuilder._current; |
| 994 environment = condBuilder.environment; | 1000 environment = condBuilder.environment; |
| 995 } | 1001 } |
| 996 } | 1002 } |
| 997 | 1003 |
| 998 /// Creates a for-in loop, `for (v in e) b`. | 1004 /// Creates a for-in loop, `for (v in e) b`. |
| 999 /// | 1005 /// |
| 1000 /// [buildExpression] creates the expression, `e`. The variable, `v`, can | 1006 /// [buildExpression] creates the expression, `e`. The variable, `v`, can |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1031 // } | 1037 // } |
| 1032 | 1038 |
| 1033 // The condition and body are delimited. | 1039 // The condition and body are delimited. |
| 1034 IrBuilder condBuilder = makeRecursiveBuilder(); | 1040 IrBuilder condBuilder = makeRecursiveBuilder(); |
| 1035 | 1041 |
| 1036 ir.Primitive expressionReceiver = buildExpression(this); | 1042 ir.Primitive expressionReceiver = buildExpression(this); |
| 1037 List<ir.Primitive> emptyArguments = new List<ir.Primitive>(); | 1043 List<ir.Primitive> emptyArguments = new List<ir.Primitive>(); |
| 1038 | 1044 |
| 1039 ir.Parameter iterator = new ir.Parameter(null); | 1045 ir.Parameter iterator = new ir.Parameter(null); |
| 1040 ir.Continuation iteratorInvoked = new ir.Continuation([iterator]); | 1046 ir.Continuation iteratorInvoked = new ir.Continuation([iterator]); |
| 1041 add(new ir.LetCont(iteratorInvoked, | 1047 add(new ir.LetCont(<ir.Continuation>[iteratorInvoked], |
| 1042 new ir.InvokeMethod(expressionReceiver, | 1048 new ir.InvokeMethod(expressionReceiver, |
| 1043 new Selector.getter("iterator", null), iteratorInvoked, | 1049 new Selector.getter("iterator", null), iteratorInvoked, |
| 1044 emptyArguments))); | 1050 emptyArguments))); |
| 1045 | 1051 |
| 1046 ir.Parameter condition = new ir.Parameter(null); | 1052 ir.Parameter condition = new ir.Parameter(null); |
| 1047 ir.Continuation moveNextInvoked = new ir.Continuation([condition]); | 1053 ir.Continuation moveNextInvoked = new ir.Continuation([condition]); |
| 1048 condBuilder.add(new ir.LetCont(moveNextInvoked, | 1054 condBuilder.add(new ir.LetCont(<ir.Continuation>[moveNextInvoked], |
| 1049 new ir.InvokeMethod(iterator, | 1055 new ir.InvokeMethod(iterator, |
| 1050 new Selector.call("moveNext", null, 0), | 1056 new Selector.call("moveNext", null, 0), |
| 1051 moveNextInvoked, emptyArguments))); | 1057 moveNextInvoked, emptyArguments))); |
| 1052 | 1058 |
| 1053 JumpCollector breakCollector = new JumpCollector(target); | 1059 JumpCollector breakCollector = new JumpCollector(target); |
| 1054 JumpCollector continueCollector = new JumpCollector(target); | 1060 JumpCollector continueCollector = new JumpCollector(target); |
| 1055 state.breakCollectors.add(breakCollector); | 1061 state.breakCollectors.add(breakCollector); |
| 1056 state.continueCollectors.add(continueCollector); | 1062 state.continueCollectors.add(continueCollector); |
| 1057 | 1063 |
| 1058 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder(); | 1064 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder(); |
| 1059 bodyBuilder._enterScope(closureScope); | 1065 bodyBuilder._enterScope(closureScope); |
| 1060 if (buildVariableDeclaration != null) { | 1066 if (buildVariableDeclaration != null) { |
| 1061 buildVariableDeclaration(bodyBuilder); | 1067 buildVariableDeclaration(bodyBuilder); |
| 1062 } | 1068 } |
| 1063 | 1069 |
| 1064 ir.Parameter currentValue = new ir.Parameter(null); | 1070 ir.Parameter currentValue = new ir.Parameter(null); |
| 1065 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); | 1071 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); |
| 1066 bodyBuilder.add(new ir.LetCont(currentInvoked, | 1072 bodyBuilder.add(new ir.LetCont(<ir.Continuation>[currentInvoked], |
| 1067 new ir.InvokeMethod(iterator, new Selector.getter("current", null), | 1073 new ir.InvokeMethod(iterator, new Selector.getter("current", null), |
| 1068 currentInvoked, emptyArguments))); | 1074 currentInvoked, emptyArguments))); |
| 1069 if (Elements.isLocal(variableElement)) { | 1075 if (Elements.isLocal(variableElement)) { |
| 1070 bodyBuilder.buildLocalSet(variableElement, currentValue); | 1076 bodyBuilder.buildLocalSet(variableElement, currentValue); |
| 1071 } else if (Elements.isStaticOrTopLevel(variableElement)) { | 1077 } else if (Elements.isStaticOrTopLevel(variableElement)) { |
| 1072 bodyBuilder.buildStaticSet( | 1078 bodyBuilder.buildStaticSet( |
| 1073 variableElement, variableSelector, currentValue); | 1079 variableElement, variableSelector, currentValue); |
| 1074 } else { | 1080 } else { |
| 1075 ir.Primitive receiver = bodyBuilder.buildThis(); | 1081 ir.Primitive receiver = bodyBuilder.buildThis(); |
| 1076 bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue); | 1082 bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue); |
| 1077 } | 1083 } |
| 1078 | 1084 |
| 1079 buildBody(bodyBuilder); | 1085 buildBody(bodyBuilder); |
| 1080 assert(state.breakCollectors.last == breakCollector); | 1086 assert(state.breakCollectors.last == breakCollector); |
| 1081 assert(state.continueCollectors.last == continueCollector); | 1087 assert(state.continueCollectors.last == continueCollector); |
| 1082 state.breakCollectors.removeLast(); | 1088 state.breakCollectors.removeLast(); |
| 1083 state.continueCollectors.removeLast(); | 1089 state.continueCollectors.removeLast(); |
| 1084 | 1090 |
| 1085 // Create body entry and loop exit continuations and a branch to them. | 1091 // Create body entry and loop exit continuations and a branch to them. |
| 1086 ir.Continuation bodyContinuation = new ir.Continuation([]); | 1092 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 1087 ir.Continuation exitContinuation = new ir.Continuation([]); | 1093 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1094 // Note the order of continuations: the first one is the one that will |
| 1095 // be filled by LetCont.plug. |
| 1088 ir.LetCont branch = | 1096 ir.LetCont branch = |
| 1089 new ir.LetCont(exitContinuation, | 1097 new ir.LetCont(<ir.Continuation>[exitContinuation, bodyContinuation], |
| 1090 new ir.LetCont(bodyContinuation, | 1098 new ir.Branch(new ir.IsTrue(condition), |
| 1091 new ir.Branch(new ir.IsTrue(condition), | 1099 bodyContinuation, |
| 1092 bodyContinuation, | 1100 exitContinuation)); |
| 1093 exitContinuation))); | |
| 1094 // If there are breaks in the body, then there must be a join-point | 1101 // If there are breaks in the body, then there must be a join-point |
| 1095 // continuation for the normal exit and the breaks. | 1102 // continuation for the normal exit and the breaks. |
| 1096 bool hasBreaks = !breakCollector.isEmpty; | 1103 bool hasBreaks = !breakCollector.isEmpty; |
| 1097 ir.LetCont letJoin; | 1104 ir.LetCont letJoin; |
| 1098 if (hasBreaks) { | 1105 if (hasBreaks) { |
| 1099 letJoin = new ir.LetCont(null, branch); | 1106 letJoin = new ir.LetCont(null, branch); |
| 1100 condBuilder.add(letJoin); | 1107 condBuilder.add(letJoin); |
| 1101 condBuilder._current = branch; | 1108 condBuilder._current = branch; |
| 1102 } else { | 1109 } else { |
| 1103 condBuilder.add(branch); | 1110 condBuilder.add(branch); |
| 1104 } | 1111 } |
| 1105 ir.Continuation loopContinuation = | 1112 ir.Continuation loopContinuation = |
| 1106 new ir.Continuation(condBuilder._parameters); | 1113 new ir.Continuation(condBuilder._parameters); |
| 1107 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); | 1114 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); |
| 1108 invokeFullJoin( | 1115 invokeFullJoin( |
| 1109 loopContinuation, continueCollector, recursive: true); | 1116 loopContinuation, continueCollector, recursive: true); |
| 1110 bodyContinuation.body = bodyBuilder._root; | 1117 bodyContinuation.body = bodyBuilder._root; |
| 1111 | 1118 |
| 1112 loopContinuation.body = condBuilder._root; | 1119 loopContinuation.body = condBuilder._root; |
| 1113 add(new ir.LetCont(loopContinuation, | 1120 add(new ir.LetCont(<ir.Continuation>[loopContinuation], |
| 1114 new ir.InvokeContinuation(loopContinuation, | 1121 new ir.InvokeContinuation(loopContinuation, |
| 1115 environment.index2value))); | 1122 environment.index2value))); |
| 1116 if (hasBreaks) { | 1123 if (hasBreaks) { |
| 1117 _current = branch; | 1124 _current = branch; |
| 1118 environment = condBuilder.environment; | 1125 environment = condBuilder.environment; |
| 1119 breakCollector.addJump(this); | 1126 breakCollector.addJump(this); |
| 1120 letJoin.continuation = createJoin(environment.length, breakCollector); | 1127 letJoin.continuations = |
| 1128 <ir.Continuation>[createJoin(environment.length, breakCollector)]; |
| 1121 _current = letJoin; | 1129 _current = letJoin; |
| 1122 } else { | 1130 } else { |
| 1123 _current = condBuilder._current; | 1131 _current = condBuilder._current; |
| 1124 environment = condBuilder.environment; | 1132 environment = condBuilder.environment; |
| 1125 } | 1133 } |
| 1126 } | 1134 } |
| 1127 | 1135 |
| 1128 /// Creates a while loop in which the condition and body are created by | 1136 /// Creates a while loop in which the condition and body are created by |
| 1129 /// [buildCondition] and [buildBody], respectively. | 1137 /// [buildCondition] and [buildBody], respectively. |
| 1130 /// | 1138 /// |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 bodyBuilder._enterScope(closureScope); | 1172 bodyBuilder._enterScope(closureScope); |
| 1165 buildBody(bodyBuilder); | 1173 buildBody(bodyBuilder); |
| 1166 assert(state.breakCollectors.last == breakCollector); | 1174 assert(state.breakCollectors.last == breakCollector); |
| 1167 assert(state.continueCollectors.last == continueCollector); | 1175 assert(state.continueCollectors.last == continueCollector); |
| 1168 state.breakCollectors.removeLast(); | 1176 state.breakCollectors.removeLast(); |
| 1169 state.continueCollectors.removeLast(); | 1177 state.continueCollectors.removeLast(); |
| 1170 | 1178 |
| 1171 // Create body entry and loop exit continuations and a branch to them. | 1179 // Create body entry and loop exit continuations and a branch to them. |
| 1172 ir.Continuation bodyContinuation = new ir.Continuation([]); | 1180 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 1173 ir.Continuation exitContinuation = new ir.Continuation([]); | 1181 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1182 // Note the order of continuations: the first one is the one that will |
| 1183 // be filled by LetCont.plug. |
| 1174 ir.LetCont branch = | 1184 ir.LetCont branch = |
| 1175 new ir.LetCont(exitContinuation, | 1185 new ir.LetCont(<ir.Continuation>[exitContinuation, bodyContinuation], |
| 1176 new ir.LetCont(bodyContinuation, | 1186 new ir.Branch(new ir.IsTrue(condition), |
| 1177 new ir.Branch(new ir.IsTrue(condition), | 1187 bodyContinuation, |
| 1178 bodyContinuation, | 1188 exitContinuation)); |
| 1179 exitContinuation))); | |
| 1180 // If there are breaks in the body, then there must be a join-point | 1189 // If there are breaks in the body, then there must be a join-point |
| 1181 // continuation for the normal exit and the breaks. | 1190 // continuation for the normal exit and the breaks. |
| 1182 bool hasBreaks = !breakCollector.isEmpty; | 1191 bool hasBreaks = !breakCollector.isEmpty; |
| 1183 ir.LetCont letJoin; | 1192 ir.LetCont letJoin; |
| 1184 if (hasBreaks) { | 1193 if (hasBreaks) { |
| 1185 letJoin = new ir.LetCont(null, branch); | 1194 letJoin = new ir.LetCont(null, branch); |
| 1186 condBuilder.add(letJoin); | 1195 condBuilder.add(letJoin); |
| 1187 condBuilder._current = branch; | 1196 condBuilder._current = branch; |
| 1188 } else { | 1197 } else { |
| 1189 condBuilder.add(branch); | 1198 condBuilder.add(branch); |
| 1190 } | 1199 } |
| 1191 ir.Continuation loopContinuation = | 1200 ir.Continuation loopContinuation = |
| 1192 new ir.Continuation(condBuilder._parameters); | 1201 new ir.Continuation(condBuilder._parameters); |
| 1193 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); | 1202 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); |
| 1194 invokeFullJoin(loopContinuation, continueCollector, recursive: true); | 1203 invokeFullJoin(loopContinuation, continueCollector, recursive: true); |
| 1195 bodyContinuation.body = bodyBuilder._root; | 1204 bodyContinuation.body = bodyBuilder._root; |
| 1196 | 1205 |
| 1197 loopContinuation.body = condBuilder._root; | 1206 loopContinuation.body = condBuilder._root; |
| 1198 add(new ir.LetCont(loopContinuation, | 1207 add(new ir.LetCont(<ir.Continuation>[loopContinuation], |
| 1199 new ir.InvokeContinuation(loopContinuation, | 1208 new ir.InvokeContinuation(loopContinuation, |
| 1200 environment.index2value))); | 1209 environment.index2value))); |
| 1201 if (hasBreaks) { | 1210 if (hasBreaks) { |
| 1202 _current = branch; | 1211 _current = branch; |
| 1203 environment = condBuilder.environment; | 1212 environment = condBuilder.environment; |
| 1204 breakCollector.addJump(this); | 1213 breakCollector.addJump(this); |
| 1205 letJoin.continuation = createJoin(environment.length, breakCollector); | 1214 letJoin.continuations = |
| 1215 <ir.Continuation>[createJoin(environment.length, breakCollector)]; |
| 1206 _current = letJoin; | 1216 _current = letJoin; |
| 1207 } else { | 1217 } else { |
| 1208 _current = condBuilder._current; | 1218 _current = condBuilder._current; |
| 1209 environment = condBuilder.environment; | 1219 environment = condBuilder.environment; |
| 1210 } | 1220 } |
| 1211 } | 1221 } |
| 1212 | 1222 |
| 1213 /// Create a return statement `return value;` or `return;` if [value] is | 1223 /// Create a return statement `return value;` or `return;` if [value] is |
| 1214 /// null. | 1224 /// null. |
| 1215 void buildReturn([ir.Primitive value]) { | 1225 void buildReturn([ir.Primitive value]) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 } | 1304 } |
| 1295 | 1305 |
| 1296 ir.Constant trueConstant = makeBoolConstant(true); | 1306 ir.Constant trueConstant = makeBoolConstant(true); |
| 1297 ir.Constant falseConstant = makeBoolConstant(false); | 1307 ir.Constant falseConstant = makeBoolConstant(false); |
| 1298 | 1308 |
| 1299 thenContinuation.body = new ir.LetPrim(falseConstant) | 1309 thenContinuation.body = new ir.LetPrim(falseConstant) |
| 1300 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); | 1310 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); |
| 1301 elseContinuation.body = new ir.LetPrim(trueConstant) | 1311 elseContinuation.body = new ir.LetPrim(trueConstant) |
| 1302 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); | 1312 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); |
| 1303 | 1313 |
| 1304 add(new ir.LetCont(joinContinuation, | 1314 add(new ir.LetCont(<ir.Continuation>[joinContinuation], |
| 1305 new ir.LetCont(thenContinuation, | 1315 new ir.LetCont(<ir.Continuation>[thenContinuation, elseContinuation], |
| 1306 new ir.LetCont(elseContinuation, | |
| 1307 new ir.Branch(new ir.IsTrue(condition), | 1316 new ir.Branch(new ir.IsTrue(condition), |
| 1308 thenContinuation, | 1317 thenContinuation, |
| 1309 elseContinuation))))); | 1318 elseContinuation)))); |
| 1310 return resultParameter; | 1319 return resultParameter; |
| 1311 } | 1320 } |
| 1312 | 1321 |
| 1313 /// Creates a type test or type cast of [receiver] against [type]. | 1322 /// Creates a type test or type cast of [receiver] against [type]. |
| 1314 /// | 1323 /// |
| 1315 /// Set [isTypeTest] to `true` to create a type test and furthermore set | 1324 /// Set [isTypeTest] to `true` to create a type test and furthermore set |
| 1316 /// [isNotCheck] to `true` to create a negated type test. | 1325 /// [isNotCheck] to `true` to create a negated type test. |
| 1317 ir.Primitive buildTypeOperator(ir.Primitive receiver, | 1326 ir.Primitive buildTypeOperator(ir.Primitive receiver, |
| 1318 DartType type, | 1327 DartType type, |
| 1319 {bool isTypeTest: false, | 1328 {bool isTypeTest: false, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1378 ir.Continuation joinContinuation = | 1387 ir.Continuation joinContinuation = |
| 1379 createJoin(environment.length + 1, jumps); | 1388 createJoin(environment.length + 1, jumps); |
| 1380 ir.Continuation leftTrueContinuation = new ir.Continuation([]); | 1389 ir.Continuation leftTrueContinuation = new ir.Continuation([]); |
| 1381 ir.Continuation leftFalseContinuation = new ir.Continuation([]); | 1390 ir.Continuation leftFalseContinuation = new ir.Continuation([]); |
| 1382 ir.Continuation rightTrueContinuation = new ir.Continuation([]); | 1391 ir.Continuation rightTrueContinuation = new ir.Continuation([]); |
| 1383 ir.Continuation rightFalseContinuation = new ir.Continuation([]); | 1392 ir.Continuation rightFalseContinuation = new ir.Continuation([]); |
| 1384 rightTrueContinuation.body = rightTrueBuilder._root; | 1393 rightTrueContinuation.body = rightTrueBuilder._root; |
| 1385 rightFalseContinuation.body = rightFalseBuilder._root; | 1394 rightFalseContinuation.body = rightFalseBuilder._root; |
| 1386 // The right subexpression has two continuations. | 1395 // The right subexpression has two continuations. |
| 1387 rightBuilder.add( | 1396 rightBuilder.add( |
| 1388 new ir.LetCont(rightTrueContinuation, | 1397 new ir.LetCont(<ir.Continuation>[rightTrueContinuation, |
| 1389 new ir.LetCont(rightFalseContinuation, | 1398 rightFalseContinuation], |
| 1390 new ir.Branch(new ir.IsTrue(rightValue), | 1399 new ir.Branch(new ir.IsTrue(rightValue), |
| 1391 rightTrueContinuation, | 1400 rightTrueContinuation, |
| 1392 rightFalseContinuation)))); | 1401 rightFalseContinuation))); |
| 1393 // Depending on the operator, the left subexpression's continuations are | 1402 // Depending on the operator, the left subexpression's continuations are |
| 1394 // either the right subexpression or an invocation of the join-point | 1403 // either the right subexpression or an invocation of the join-point |
| 1395 // continuation. | 1404 // continuation. |
| 1396 if (isLazyOr) { | 1405 if (isLazyOr) { |
| 1397 leftTrueContinuation.body = emptyBuilder._root; | 1406 leftTrueContinuation.body = emptyBuilder._root; |
| 1398 leftFalseContinuation.body = rightBuilder._root; | 1407 leftFalseContinuation.body = rightBuilder._root; |
| 1399 } else { | 1408 } else { |
| 1400 leftTrueContinuation.body = rightBuilder._root; | 1409 leftTrueContinuation.body = rightBuilder._root; |
| 1401 leftFalseContinuation.body = emptyBuilder._root; | 1410 leftFalseContinuation.body = emptyBuilder._root; |
| 1402 } | 1411 } |
| 1403 | 1412 |
| 1404 add(new ir.LetCont(joinContinuation, | 1413 add(new ir.LetCont(<ir.Continuation>[joinContinuation], |
| 1405 new ir.LetCont(leftTrueContinuation, | 1414 new ir.LetCont(<ir.Continuation>[leftTrueContinuation, |
| 1406 new ir.LetCont(leftFalseContinuation, | 1415 leftFalseContinuation], |
| 1407 new ir.Branch(new ir.IsTrue(leftValue), | 1416 new ir.Branch(new ir.IsTrue(leftValue), |
| 1408 leftTrueContinuation, | 1417 leftTrueContinuation, |
| 1409 leftFalseContinuation))))); | 1418 leftFalseContinuation)))); |
| 1410 // There is always a join parameter for the result value, because it | 1419 // There is always a join parameter for the result value, because it |
| 1411 // is different on at least two paths. | 1420 // is different on at least two paths. |
| 1412 return joinContinuation.parameters.last; | 1421 return joinContinuation.parameters.last; |
| 1413 } | 1422 } |
| 1414 | 1423 |
| 1415 /// Create a non-recursive join-point continuation. | 1424 /// Create a non-recursive join-point continuation. |
| 1416 /// | 1425 /// |
| 1417 /// Given the environment length at the join point and a list of | 1426 /// Given the environment length at the join point and a list of |
| 1418 /// jumps that should reach the join point, create a join-point | 1427 /// jumps that should reach the join point, create a join-point |
| 1419 /// continuation. The join-point continuation has a parameter for each | 1428 /// continuation. The join-point continuation has a parameter for each |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1979 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); | 1988 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); |
| 1980 } | 1989 } |
| 1981 | 1990 |
| 1982 /// Information about which variables are captured in a closure. | 1991 /// Information about which variables are captured in a closure. |
| 1983 /// | 1992 /// |
| 1984 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and | 1993 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and |
| 1985 /// [ClosureEnvironment]. | 1994 /// [ClosureEnvironment]. |
| 1986 abstract class ClosureVariableInfo { | 1995 abstract class ClosureVariableInfo { |
| 1987 Iterable<Local> get capturedVariables; | 1996 Iterable<Local> get capturedVariables; |
| 1988 } | 1997 } |
| OLD | NEW |