Chromium Code Reviews| 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 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 _root = _current = expr; | 390 _root = _current = expr; |
| 391 } else { | 391 } else { |
| 392 _current = _current.plug(expr); | 392 _current = _current.plug(expr); |
| 393 } | 393 } |
| 394 } | 394 } |
| 395 | 395 |
| 396 ir.Primitive _continueWithExpression(ir.Expression build(ir.Continuation k)) { | 396 ir.Primitive _continueWithExpression(ir.Expression build(ir.Continuation k)) { |
| 397 ir.Parameter v = new ir.Parameter(null); | 397 ir.Parameter v = new ir.Parameter(null); |
| 398 ir.Continuation k = new ir.Continuation([v]); | 398 ir.Continuation k = new ir.Continuation([v]); |
| 399 ir.Expression expression = build(k); | 399 ir.Expression expression = build(k); |
| 400 add(new ir.LetCont(k, expression)); | 400 add(new ir.LetCont(<ir.Continuation>[k], expression)); |
|
asgerf
2015/01/15 15:29:45
It may be nicer to introduce a named constructor f
| |
| 401 return v; | 401 return v; |
| 402 } | 402 } |
| 403 | 403 |
| 404 ir.Primitive _buildInvokeStatic(Element element, | 404 ir.Primitive _buildInvokeStatic(Element element, |
| 405 Selector selector, | 405 Selector selector, |
| 406 List<ir.Primitive> arguments) { | 406 List<ir.Primitive> arguments) { |
| 407 assert(isOpen); | 407 assert(isOpen); |
| 408 return _continueWithExpression( | 408 return _continueWithExpression( |
| 409 (k) => new ir.InvokeStatic(element, selector, k, arguments)); | 409 (k) => new ir.InvokeStatic(element, selector, k, arguments)); |
| 410 } | 410 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 528 elseBuilder.environment.extend(null, elseValue); | 528 elseBuilder.environment.extend(null, elseValue); |
| 529 JumpCollector jumps = new JumpCollector(null); | 529 JumpCollector jumps = new JumpCollector(null); |
| 530 jumps.addJump(thenBuilder); | 530 jumps.addJump(thenBuilder); |
| 531 jumps.addJump(elseBuilder); | 531 jumps.addJump(elseBuilder); |
| 532 ir.Continuation joinContinuation = | 532 ir.Continuation joinContinuation = |
| 533 createJoin(environment.length + 1, jumps); | 533 createJoin(environment.length + 1, jumps); |
| 534 | 534 |
| 535 // Build the term | 535 // Build the term |
| 536 // let cont join(x, ..., result) = [] in | 536 // let cont join(x, ..., result) = [] in |
| 537 // let cont then() = [[thenPart]]; join(v, ...) in | 537 // let cont then() = [[thenPart]]; join(v, ...) in |
| 538 // let cont else() = [[elsePart]]; join(v, ...) in | 538 // let cont else() = [[elsePart]]; join(v, ...) in |
|
asgerf
2015/01/15 15:29:45
'let cont else()' --> 'and cont else()' ?
| |
| 539 // if condition (then, else) | 539 // if condition (then, else) |
| 540 ir.Continuation thenContinuation = new ir.Continuation([]); | 540 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 541 ir.Continuation elseContinuation = new ir.Continuation([]); | 541 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 542 thenContinuation.body = thenBuilder._root; | 542 thenContinuation.body = thenBuilder._root; |
| 543 elseContinuation.body = elseBuilder._root; | 543 elseContinuation.body = elseBuilder._root; |
| 544 add(new ir.LetCont(joinContinuation, | 544 add(new ir.LetCont(<ir.Continuation>[joinContinuation], |
| 545 new ir.LetCont(thenContinuation, | 545 new ir.LetCont(<ir.Continuation>[thenContinuation, |
| 546 new ir.LetCont(elseContinuation, | 546 elseContinuation], |
| 547 new ir.Branch(new ir.IsTrue(condition), | 547 new ir.Branch(new ir.IsTrue(condition), |
| 548 thenContinuation, | 548 thenContinuation, |
| 549 elseContinuation))))); | 549 elseContinuation)))); |
| 550 return (thenValue == elseValue) | 550 return (thenValue == elseValue) |
| 551 ? thenValue | 551 ? thenValue |
| 552 : joinContinuation.parameters.last; | 552 : joinContinuation.parameters.last; |
| 553 | |
| 554 } | 553 } |
| 555 | 554 |
| 556 /** | 555 /** |
| 557 * Add an explicit `return null` for functions that don't have a return | 556 * Add an explicit `return null` for functions that don't have a return |
| 558 * statement on each branch. This includes functions with an empty body, | 557 * statement on each branch. This includes functions with an empty body, |
| 559 * such as `foo(){ }`. | 558 * such as `foo(){ }`. |
| 560 */ | 559 */ |
| 561 void _ensureReturn() { | 560 void _ensureReturn() { |
| 562 if (!isOpen) return; | 561 if (!isOpen) return; |
| 563 ir.Constant constant = buildNullLiteral(); | 562 ir.Constant constant = buildNullLiteral(); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 786 IrBuilder elseBuilder = makeDelimitedBuilder(); | 785 IrBuilder elseBuilder = makeDelimitedBuilder(); |
| 787 buildThenPart(thenBuilder); | 786 buildThenPart(thenBuilder); |
| 788 buildElsePart(elseBuilder); | 787 buildElsePart(elseBuilder); |
| 789 | 788 |
| 790 // Build the term | 789 // Build the term |
| 791 // (Result =) let cont then() = [[thenPart]] in | 790 // (Result =) let cont then() = [[thenPart]] in |
| 792 // let cont else() = [[elsePart]] in | 791 // let cont else() = [[elsePart]] in |
| 793 // if condition (then, else) | 792 // if condition (then, else) |
| 794 ir.Continuation thenContinuation = new ir.Continuation([]); | 793 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 795 ir.Continuation elseContinuation = new ir.Continuation([]); | 794 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 796 ir.Expression letElse = | 795 // If exactly one of the then and else continuation bodies is open (i.e., |
| 797 new ir.LetCont(elseContinuation, | 796 // the other one has an exit on all paths), then Continuation.plug expects |
| 798 new ir.Branch(new ir.IsTrue(condition), | 797 // that continuation to be listed first. Arbitrarily use [then, else] |
| 799 thenContinuation, | 798 // order otherwise. |
| 800 elseContinuation)); | 799 List<ir.Continuation> arms = !thenBuilder.isOpen && elseBuilder.isOpen |
| 801 ir.Expression letThen = new ir.LetCont(thenContinuation, letElse); | 800 ? <ir.Continuation>[elseContinuation, thenContinuation] |
| 802 ir.Expression result = letThen; | 801 : <ir.Continuation>[thenContinuation, elseContinuation]; |
| 802 | |
| 803 ir.Expression result = | |
| 804 new ir.LetCont(arms, | |
| 805 new ir.Branch(new ir.IsTrue(condition), | |
| 806 thenContinuation, | |
| 807 elseContinuation)); | |
| 803 | 808 |
| 804 ir.Continuation joinContinuation; // Null if there is no join. | 809 ir.Continuation joinContinuation; // Null if there is no join. |
| 805 if (thenBuilder.isOpen && elseBuilder.isOpen) { | 810 if (thenBuilder.isOpen && elseBuilder.isOpen) { |
| 806 // There is a join-point continuation. Build the term | 811 // There is a join-point continuation. Build the term |
| 807 // 'let cont join(x, ...) = [] in Result' and plug invocations of the | 812 // 'let cont join(x, ...) = [] in Result' and plug invocations of the |
| 808 // join-point continuation into the then and else continuations. | 813 // join-point continuation into the then and else continuations. |
| 809 JumpCollector jumps = new JumpCollector(null); | 814 JumpCollector jumps = new JumpCollector(null); |
| 810 jumps.addJump(thenBuilder); | 815 jumps.addJump(thenBuilder); |
| 811 jumps.addJump(elseBuilder); | 816 jumps.addJump(elseBuilder); |
| 812 joinContinuation = createJoin(environment.length, jumps); | 817 joinContinuation = createJoin(environment.length, jumps); |
| 813 result = new ir.LetCont(joinContinuation, result); | 818 result = new ir.LetCont(<ir.Continuation>[joinContinuation], result); |
| 814 } | 819 } |
| 815 | 820 |
| 816 // The then or else term root could be null, but not both. If there is | 821 // The then or else term root could be null, but not both. If there is |
| 817 // a join then an InvokeContinuation was just added to both of them. If | 822 // a join then an InvokeContinuation was just added to both of them. If |
| 818 // there is no join, then at least one of them is closed and thus has a | 823 // there is no join, then at least one of them is closed and thus has a |
| 819 // non-null root by the definition of the predicate isClosed. In the | 824 // non-null root by the definition of the predicate isClosed. In the |
| 820 // case that one of them is null, it must be the only one that is open | 825 // case that one of them is null, it must be the only one that is open |
| 821 // and thus contains the new hole in the context. This case is handled | 826 // and thus contains the new hole in the context. This case is handled |
| 822 // after the branch is plugged into the current hole. | 827 // after the branch is plugged into the current hole. |
| 823 thenContinuation.body = thenBuilder._root; | 828 thenContinuation.body = thenBuilder._root; |
| 824 elseContinuation.body = elseBuilder._root; | 829 elseContinuation.body = elseBuilder._root; |
| 825 | 830 |
| 826 add(result); | 831 add(result); |
| 827 if (joinContinuation == null) { | 832 if (joinContinuation == null) { |
| 828 // At least one subexpression is closed. | 833 // At least one subexpression is closed. |
| 829 if (thenBuilder.isOpen) { | 834 if (thenBuilder.isOpen) { |
| 830 _current = | 835 if (thenBuilder._root != null) _current = thenBuilder._current; |
| 831 (thenBuilder._root == null) ? letThen : thenBuilder._current; | |
| 832 environment = thenBuilder.environment; | 836 environment = thenBuilder.environment; |
| 833 } else if (elseBuilder.isOpen) { | 837 } else if (elseBuilder.isOpen) { |
| 834 _current = | 838 if (elseBuilder._root != null) _current = elseBuilder._current; |
| 835 (elseBuilder._root == null) ? letElse : elseBuilder._current; | |
| 836 environment = elseBuilder.environment; | 839 environment = elseBuilder.environment; |
| 837 } else { | 840 } else { |
| 838 _current = null; | 841 _current = null; |
| 839 } | 842 } |
| 840 } | 843 } |
| 841 } | 844 } |
| 842 | 845 |
| 843 /// Invoke a join-point continuation that contains arguments for all local | 846 /// Invoke a join-point continuation that contains arguments for all local |
| 844 /// variables. | 847 /// variables. |
| 845 /// | 848 /// |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 951 ? condBuilder.makeRecursiveBuilder() | 954 ? condBuilder.makeRecursiveBuilder() |
| 952 : bodyBuilder; | 955 : bodyBuilder; |
| 953 if (hasBoxedLoopVariables) { | 956 if (hasBoxedLoopVariables) { |
| 954 updateBuilder._migrateLoopVariables(closureScope); | 957 updateBuilder._migrateLoopVariables(closureScope); |
| 955 } | 958 } |
| 956 buildUpdate(updateBuilder); | 959 buildUpdate(updateBuilder); |
| 957 | 960 |
| 958 // Create body entry and loop exit continuations and a branch to them. | 961 // Create body entry and loop exit continuations and a branch to them. |
| 959 ir.Continuation bodyContinuation = new ir.Continuation([]); | 962 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 960 ir.Continuation exitContinuation = new ir.Continuation([]); | 963 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 964 // Note the order of continuations: the first one is the one that will | |
| 965 // be filled by LetCont.plug. | |
| 961 ir.LetCont branch = | 966 ir.LetCont branch = |
| 962 new ir.LetCont(exitContinuation, | 967 new ir.LetCont(<ir.Continuation>[exitContinuation, bodyContinuation], |
| 963 new ir.LetCont(bodyContinuation, | 968 new ir.Branch(new ir.IsTrue(condition), |
| 964 new ir.Branch(new ir.IsTrue(condition), | 969 bodyContinuation, |
| 965 bodyContinuation, | 970 exitContinuation)); |
| 966 exitContinuation))); | |
| 967 // If there are breaks in the body, then there must be a join-point | 971 // If there are breaks in the body, then there must be a join-point |
| 968 // continuation for the normal exit and the breaks. | 972 // continuation for the normal exit and the breaks. |
| 969 bool hasBreaks = !breakCollector.isEmpty; | 973 bool hasBreaks = !breakCollector.isEmpty; |
| 970 ir.LetCont letJoin; | 974 ir.LetCont letJoin; |
| 971 if (hasBreaks) { | 975 if (hasBreaks) { |
| 972 letJoin = new ir.LetCont(null, branch); | 976 letJoin = new ir.LetCont(null, branch); |
| 973 condBuilder.add(letJoin); | 977 condBuilder.add(letJoin); |
| 974 condBuilder._current = branch; | 978 condBuilder._current = branch; |
| 975 } else { | 979 } else { |
| 976 condBuilder.add(branch); | 980 condBuilder.add(branch); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 989 JumpCollector backEdges = new JumpCollector(null); | 993 JumpCollector backEdges = new JumpCollector(null); |
| 990 backEdges.addJump(updateBuilder); | 994 backEdges.addJump(updateBuilder); |
| 991 invokeFullJoin(loopContinuation, backEdges, recursive: true); | 995 invokeFullJoin(loopContinuation, backEdges, recursive: true); |
| 992 } | 996 } |
| 993 | 997 |
| 994 // Fill in the body and possible continue continuation bodies. Do this | 998 // Fill in the body and possible continue continuation bodies. Do this |
| 995 // only after it is guaranteed that they are not empty. | 999 // only after it is guaranteed that they are not empty. |
| 996 if (hasContinues) { | 1000 if (hasContinues) { |
| 997 continueContinuation.body = updateBuilder._root; | 1001 continueContinuation.body = updateBuilder._root; |
| 998 bodyContinuation.body = | 1002 bodyContinuation.body = |
| 999 new ir.LetCont(continueContinuation, bodyBuilder._root); | 1003 new ir.LetCont(<ir.Continuation>[continueContinuation], |
| 1004 bodyBuilder._root); | |
| 1000 } else { | 1005 } else { |
| 1001 bodyContinuation.body = bodyBuilder._root; | 1006 bodyContinuation.body = bodyBuilder._root; |
| 1002 } | 1007 } |
| 1003 | 1008 |
| 1004 loopContinuation.body = condBuilder._root; | 1009 loopContinuation.body = condBuilder._root; |
| 1005 add(new ir.LetCont(loopContinuation, | 1010 add(new ir.LetCont(<ir.Continuation>[loopContinuation], |
| 1006 new ir.InvokeContinuation(loopContinuation, | 1011 new ir.InvokeContinuation(loopContinuation, |
| 1007 environment.index2value))); | 1012 environment.index2value))); |
| 1008 if (hasBreaks) { | 1013 if (hasBreaks) { |
| 1009 _current = branch; | 1014 _current = branch; |
| 1010 environment = condBuilder.environment; | 1015 environment = condBuilder.environment; |
| 1011 breakCollector.addJump(this); | 1016 breakCollector.addJump(this); |
| 1012 letJoin.continuation = createJoin(environment.length, breakCollector); | 1017 letJoin.continuations = |
| 1018 <ir.Continuation>[createJoin(environment.length, breakCollector)]; | |
| 1013 _current = letJoin; | 1019 _current = letJoin; |
| 1014 } else { | 1020 } else { |
| 1015 _current = condBuilder._current; | 1021 _current = condBuilder._current; |
| 1016 environment = condBuilder.environment; | 1022 environment = condBuilder.environment; |
| 1017 } | 1023 } |
| 1018 } | 1024 } |
| 1019 | 1025 |
| 1020 /// Creates a for-in loop, `for (v in e) b`. | 1026 /// Creates a for-in loop, `for (v in e) b`. |
| 1021 /// | 1027 /// |
| 1022 /// [buildExpression] creates the expression, `e`. The variable, `v`, can | 1028 /// [buildExpression] creates the expression, `e`. The variable, `v`, can |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1053 // } | 1059 // } |
| 1054 | 1060 |
| 1055 // The condition and body are delimited. | 1061 // The condition and body are delimited. |
| 1056 IrBuilder condBuilder = makeRecursiveBuilder(); | 1062 IrBuilder condBuilder = makeRecursiveBuilder(); |
| 1057 | 1063 |
| 1058 ir.Primitive expressionReceiver = buildExpression(this); | 1064 ir.Primitive expressionReceiver = buildExpression(this); |
| 1059 List<ir.Primitive> emptyArguments = new List<ir.Primitive>(); | 1065 List<ir.Primitive> emptyArguments = new List<ir.Primitive>(); |
| 1060 | 1066 |
| 1061 ir.Parameter iterator = new ir.Parameter(null); | 1067 ir.Parameter iterator = new ir.Parameter(null); |
| 1062 ir.Continuation iteratorInvoked = new ir.Continuation([iterator]); | 1068 ir.Continuation iteratorInvoked = new ir.Continuation([iterator]); |
| 1063 add(new ir.LetCont(iteratorInvoked, | 1069 add(new ir.LetCont(<ir.Continuation>[iteratorInvoked], |
| 1064 new ir.InvokeMethod(expressionReceiver, | 1070 new ir.InvokeMethod(expressionReceiver, |
| 1065 new Selector.getter("iterator", null), iteratorInvoked, | 1071 new Selector.getter("iterator", null), iteratorInvoked, |
| 1066 emptyArguments))); | 1072 emptyArguments))); |
| 1067 | 1073 |
| 1068 ir.Parameter condition = new ir.Parameter(null); | 1074 ir.Parameter condition = new ir.Parameter(null); |
| 1069 ir.Continuation moveNextInvoked = new ir.Continuation([condition]); | 1075 ir.Continuation moveNextInvoked = new ir.Continuation([condition]); |
| 1070 condBuilder.add(new ir.LetCont(moveNextInvoked, | 1076 condBuilder.add(new ir.LetCont(<ir.Continuation>[moveNextInvoked], |
| 1071 new ir.InvokeMethod(iterator, | 1077 new ir.InvokeMethod(iterator, |
| 1072 new Selector.call("moveNext", null, 0), | 1078 new Selector.call("moveNext", null, 0), |
| 1073 moveNextInvoked, emptyArguments))); | 1079 moveNextInvoked, emptyArguments))); |
| 1074 | 1080 |
| 1075 JumpCollector breakCollector = new JumpCollector(target); | 1081 JumpCollector breakCollector = new JumpCollector(target); |
| 1076 JumpCollector continueCollector = new JumpCollector(target); | 1082 JumpCollector continueCollector = new JumpCollector(target); |
| 1077 state.breakCollectors.add(breakCollector); | 1083 state.breakCollectors.add(breakCollector); |
| 1078 state.continueCollectors.add(continueCollector); | 1084 state.continueCollectors.add(continueCollector); |
| 1079 | 1085 |
| 1080 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder(); | 1086 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder(); |
| 1081 bodyBuilder._buildClosureScopeSetup(closureScope); | 1087 bodyBuilder._buildClosureScopeSetup(closureScope); |
| 1082 if (buildVariableDeclaration != null) { | 1088 if (buildVariableDeclaration != null) { |
| 1083 buildVariableDeclaration(bodyBuilder); | 1089 buildVariableDeclaration(bodyBuilder); |
| 1084 } | 1090 } |
| 1085 | 1091 |
| 1086 ir.Parameter currentValue = new ir.Parameter(null); | 1092 ir.Parameter currentValue = new ir.Parameter(null); |
| 1087 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); | 1093 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); |
| 1088 bodyBuilder.add(new ir.LetCont(currentInvoked, | 1094 bodyBuilder.add(new ir.LetCont(<ir.Continuation>[currentInvoked], |
| 1089 new ir.InvokeMethod(iterator, new Selector.getter("current", null), | 1095 new ir.InvokeMethod(iterator, new Selector.getter("current", null), |
| 1090 currentInvoked, emptyArguments))); | 1096 currentInvoked, emptyArguments))); |
| 1091 if (Elements.isLocal(variableElement)) { | 1097 if (Elements.isLocal(variableElement)) { |
| 1092 bodyBuilder.buildLocalSet(variableElement, currentValue); | 1098 bodyBuilder.buildLocalSet(variableElement, currentValue); |
| 1093 } else if (Elements.isStaticOrTopLevel(variableElement)) { | 1099 } else if (Elements.isStaticOrTopLevel(variableElement)) { |
| 1094 bodyBuilder.buildStaticSet( | 1100 bodyBuilder.buildStaticSet( |
| 1095 variableElement, variableSelector, currentValue); | 1101 variableElement, variableSelector, currentValue); |
| 1096 } else { | 1102 } else { |
| 1097 ir.Primitive receiver = bodyBuilder.buildThis(); | 1103 ir.Primitive receiver = bodyBuilder.buildThis(); |
| 1098 bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue); | 1104 bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue); |
| 1099 } | 1105 } |
| 1100 | 1106 |
| 1101 buildBody(bodyBuilder); | 1107 buildBody(bodyBuilder); |
| 1102 assert(state.breakCollectors.last == breakCollector); | 1108 assert(state.breakCollectors.last == breakCollector); |
| 1103 assert(state.continueCollectors.last == continueCollector); | 1109 assert(state.continueCollectors.last == continueCollector); |
| 1104 state.breakCollectors.removeLast(); | 1110 state.breakCollectors.removeLast(); |
| 1105 state.continueCollectors.removeLast(); | 1111 state.continueCollectors.removeLast(); |
| 1106 | 1112 |
| 1107 // Create body entry and loop exit continuations and a branch to them. | 1113 // Create body entry and loop exit continuations and a branch to them. |
| 1108 ir.Continuation bodyContinuation = new ir.Continuation([]); | 1114 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 1109 ir.Continuation exitContinuation = new ir.Continuation([]); | 1115 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1116 // Note the order of continuations: the first one is the one that will | |
| 1117 // be filled by LetCont.plug. | |
| 1110 ir.LetCont branch = | 1118 ir.LetCont branch = |
| 1111 new ir.LetCont(exitContinuation, | 1119 new ir.LetCont(<ir.Continuation>[exitContinuation, bodyContinuation], |
| 1112 new ir.LetCont(bodyContinuation, | 1120 new ir.Branch(new ir.IsTrue(condition), |
| 1113 new ir.Branch(new ir.IsTrue(condition), | 1121 bodyContinuation, |
| 1114 bodyContinuation, | 1122 exitContinuation)); |
| 1115 exitContinuation))); | |
| 1116 // If there are breaks in the body, then there must be a join-point | 1123 // If there are breaks in the body, then there must be a join-point |
| 1117 // continuation for the normal exit and the breaks. | 1124 // continuation for the normal exit and the breaks. |
| 1118 bool hasBreaks = !breakCollector.isEmpty; | 1125 bool hasBreaks = !breakCollector.isEmpty; |
| 1119 ir.LetCont letJoin; | 1126 ir.LetCont letJoin; |
| 1120 if (hasBreaks) { | 1127 if (hasBreaks) { |
| 1121 letJoin = new ir.LetCont(null, branch); | 1128 letJoin = new ir.LetCont(null, branch); |
| 1122 condBuilder.add(letJoin); | 1129 condBuilder.add(letJoin); |
| 1123 condBuilder._current = branch; | 1130 condBuilder._current = branch; |
| 1124 } else { | 1131 } else { |
| 1125 condBuilder.add(branch); | 1132 condBuilder.add(branch); |
| 1126 } | 1133 } |
| 1127 ir.Continuation loopContinuation = | 1134 ir.Continuation loopContinuation = |
| 1128 new ir.Continuation(condBuilder._parameters); | 1135 new ir.Continuation(condBuilder._parameters); |
| 1129 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); | 1136 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); |
| 1130 invokeFullJoin( | 1137 invokeFullJoin( |
| 1131 loopContinuation, continueCollector, recursive: true); | 1138 loopContinuation, continueCollector, recursive: true); |
| 1132 bodyContinuation.body = bodyBuilder._root; | 1139 bodyContinuation.body = bodyBuilder._root; |
| 1133 | 1140 |
| 1134 loopContinuation.body = condBuilder._root; | 1141 loopContinuation.body = condBuilder._root; |
| 1135 add(new ir.LetCont(loopContinuation, | 1142 add(new ir.LetCont(<ir.Continuation>[loopContinuation], |
| 1136 new ir.InvokeContinuation(loopContinuation, | 1143 new ir.InvokeContinuation(loopContinuation, |
| 1137 environment.index2value))); | 1144 environment.index2value))); |
| 1138 if (hasBreaks) { | 1145 if (hasBreaks) { |
| 1139 _current = branch; | 1146 _current = branch; |
| 1140 environment = condBuilder.environment; | 1147 environment = condBuilder.environment; |
| 1141 breakCollector.addJump(this); | 1148 breakCollector.addJump(this); |
| 1142 letJoin.continuation = createJoin(environment.length, breakCollector); | 1149 letJoin.continuations = |
| 1150 <ir.Continuation>[createJoin(environment.length, breakCollector)]; | |
| 1143 _current = letJoin; | 1151 _current = letJoin; |
| 1144 } else { | 1152 } else { |
| 1145 _current = condBuilder._current; | 1153 _current = condBuilder._current; |
| 1146 environment = condBuilder.environment; | 1154 environment = condBuilder.environment; |
| 1147 } | 1155 } |
| 1148 } | 1156 } |
| 1149 | 1157 |
| 1150 /// Creates a while loop in which the condition and body are created by | 1158 /// Creates a while loop in which the condition and body are created by |
| 1151 /// [buildCondition] and [buildBody], respectively. | 1159 /// [buildCondition] and [buildBody], respectively. |
| 1152 /// | 1160 /// |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1186 bodyBuilder._buildClosureScopeSetup(closureScope); | 1194 bodyBuilder._buildClosureScopeSetup(closureScope); |
| 1187 buildBody(bodyBuilder); | 1195 buildBody(bodyBuilder); |
| 1188 assert(state.breakCollectors.last == breakCollector); | 1196 assert(state.breakCollectors.last == breakCollector); |
| 1189 assert(state.continueCollectors.last == continueCollector); | 1197 assert(state.continueCollectors.last == continueCollector); |
| 1190 state.breakCollectors.removeLast(); | 1198 state.breakCollectors.removeLast(); |
| 1191 state.continueCollectors.removeLast(); | 1199 state.continueCollectors.removeLast(); |
| 1192 | 1200 |
| 1193 // Create body entry and loop exit continuations and a branch to them. | 1201 // Create body entry and loop exit continuations and a branch to them. |
| 1194 ir.Continuation bodyContinuation = new ir.Continuation([]); | 1202 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 1195 ir.Continuation exitContinuation = new ir.Continuation([]); | 1203 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1204 // Note the order of continuations: the first one is the one that will | |
| 1205 // be filled by LetCont.plug. | |
| 1196 ir.LetCont branch = | 1206 ir.LetCont branch = |
| 1197 new ir.LetCont(exitContinuation, | 1207 new ir.LetCont(<ir.Continuation>[exitContinuation, bodyContinuation], |
| 1198 new ir.LetCont(bodyContinuation, | 1208 new ir.Branch(new ir.IsTrue(condition), |
| 1199 new ir.Branch(new ir.IsTrue(condition), | 1209 bodyContinuation, |
| 1200 bodyContinuation, | 1210 exitContinuation)); |
| 1201 exitContinuation))); | |
| 1202 // If there are breaks in the body, then there must be a join-point | 1211 // If there are breaks in the body, then there must be a join-point |
| 1203 // continuation for the normal exit and the breaks. | 1212 // continuation for the normal exit and the breaks. |
| 1204 bool hasBreaks = !breakCollector.isEmpty; | 1213 bool hasBreaks = !breakCollector.isEmpty; |
| 1205 ir.LetCont letJoin; | 1214 ir.LetCont letJoin; |
| 1206 if (hasBreaks) { | 1215 if (hasBreaks) { |
| 1207 letJoin = new ir.LetCont(null, branch); | 1216 letJoin = new ir.LetCont(null, branch); |
| 1208 condBuilder.add(letJoin); | 1217 condBuilder.add(letJoin); |
| 1209 condBuilder._current = branch; | 1218 condBuilder._current = branch; |
| 1210 } else { | 1219 } else { |
| 1211 condBuilder.add(branch); | 1220 condBuilder.add(branch); |
| 1212 } | 1221 } |
| 1213 ir.Continuation loopContinuation = | 1222 ir.Continuation loopContinuation = |
| 1214 new ir.Continuation(condBuilder._parameters); | 1223 new ir.Continuation(condBuilder._parameters); |
| 1215 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); | 1224 if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder); |
| 1216 invokeFullJoin(loopContinuation, continueCollector, recursive: true); | 1225 invokeFullJoin(loopContinuation, continueCollector, recursive: true); |
| 1217 bodyContinuation.body = bodyBuilder._root; | 1226 bodyContinuation.body = bodyBuilder._root; |
| 1218 | 1227 |
| 1219 loopContinuation.body = condBuilder._root; | 1228 loopContinuation.body = condBuilder._root; |
| 1220 add(new ir.LetCont(loopContinuation, | 1229 add(new ir.LetCont(<ir.Continuation>[loopContinuation], |
| 1221 new ir.InvokeContinuation(loopContinuation, | 1230 new ir.InvokeContinuation(loopContinuation, |
| 1222 environment.index2value))); | 1231 environment.index2value))); |
| 1223 if (hasBreaks) { | 1232 if (hasBreaks) { |
| 1224 _current = branch; | 1233 _current = branch; |
| 1225 environment = condBuilder.environment; | 1234 environment = condBuilder.environment; |
| 1226 breakCollector.addJump(this); | 1235 breakCollector.addJump(this); |
| 1227 letJoin.continuation = createJoin(environment.length, breakCollector); | 1236 letJoin.continuations = |
| 1237 <ir.Continuation>[createJoin(environment.length, breakCollector)]; | |
| 1228 _current = letJoin; | 1238 _current = letJoin; |
| 1229 } else { | 1239 } else { |
| 1230 _current = condBuilder._current; | 1240 _current = condBuilder._current; |
| 1231 environment = condBuilder.environment; | 1241 environment = condBuilder.environment; |
| 1232 } | 1242 } |
| 1233 } | 1243 } |
| 1234 | 1244 |
| 1235 /// Create a return statement `return value;` or `return;` if [value] is | 1245 /// Create a return statement `return value;` or `return;` if [value] is |
| 1236 /// null. | 1246 /// null. |
| 1237 void buildReturn([ir.Primitive value]) { | 1247 void buildReturn([ir.Primitive value]) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1316 } | 1326 } |
| 1317 | 1327 |
| 1318 ir.Constant trueConstant = makeBoolConstant(true); | 1328 ir.Constant trueConstant = makeBoolConstant(true); |
| 1319 ir.Constant falseConstant = makeBoolConstant(false); | 1329 ir.Constant falseConstant = makeBoolConstant(false); |
| 1320 | 1330 |
| 1321 thenContinuation.body = new ir.LetPrim(falseConstant) | 1331 thenContinuation.body = new ir.LetPrim(falseConstant) |
| 1322 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); | 1332 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); |
| 1323 elseContinuation.body = new ir.LetPrim(trueConstant) | 1333 elseContinuation.body = new ir.LetPrim(trueConstant) |
| 1324 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); | 1334 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); |
| 1325 | 1335 |
| 1326 add(new ir.LetCont(joinContinuation, | 1336 add(new ir.LetCont(<ir.Continuation>[joinContinuation], |
| 1327 new ir.LetCont(thenContinuation, | 1337 new ir.LetCont(<ir.Continuation>[thenContinuation, elseContinuation], |
| 1328 new ir.LetCont(elseContinuation, | |
| 1329 new ir.Branch(new ir.IsTrue(condition), | 1338 new ir.Branch(new ir.IsTrue(condition), |
| 1330 thenContinuation, | 1339 thenContinuation, |
| 1331 elseContinuation))))); | 1340 elseContinuation)))); |
| 1332 return resultParameter; | 1341 return resultParameter; |
| 1333 } | 1342 } |
| 1334 | 1343 |
| 1335 /// Creates a type test or type cast of [receiver] against [type]. | 1344 /// Creates a type test or type cast of [receiver] against [type]. |
| 1336 /// | 1345 /// |
| 1337 /// Set [isTypeTest] to `true` to create a type test and furthermore set | 1346 /// Set [isTypeTest] to `true` to create a type test and furthermore set |
| 1338 /// [isNotCheck] to `true` to create a negated type test. | 1347 /// [isNotCheck] to `true` to create a negated type test. |
| 1339 ir.Primitive buildTypeOperator(ir.Primitive receiver, | 1348 ir.Primitive buildTypeOperator(ir.Primitive receiver, |
| 1340 DartType type, | 1349 DartType type, |
| 1341 {bool isTypeTest: false, | 1350 {bool isTypeTest: false, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1400 ir.Continuation joinContinuation = | 1409 ir.Continuation joinContinuation = |
| 1401 createJoin(environment.length + 1, jumps); | 1410 createJoin(environment.length + 1, jumps); |
| 1402 ir.Continuation leftTrueContinuation = new ir.Continuation([]); | 1411 ir.Continuation leftTrueContinuation = new ir.Continuation([]); |
| 1403 ir.Continuation leftFalseContinuation = new ir.Continuation([]); | 1412 ir.Continuation leftFalseContinuation = new ir.Continuation([]); |
| 1404 ir.Continuation rightTrueContinuation = new ir.Continuation([]); | 1413 ir.Continuation rightTrueContinuation = new ir.Continuation([]); |
| 1405 ir.Continuation rightFalseContinuation = new ir.Continuation([]); | 1414 ir.Continuation rightFalseContinuation = new ir.Continuation([]); |
| 1406 rightTrueContinuation.body = rightTrueBuilder._root; | 1415 rightTrueContinuation.body = rightTrueBuilder._root; |
| 1407 rightFalseContinuation.body = rightFalseBuilder._root; | 1416 rightFalseContinuation.body = rightFalseBuilder._root; |
| 1408 // The right subexpression has two continuations. | 1417 // The right subexpression has two continuations. |
| 1409 rightBuilder.add( | 1418 rightBuilder.add( |
| 1410 new ir.LetCont(rightTrueContinuation, | 1419 new ir.LetCont(<ir.Continuation>[rightTrueContinuation, |
| 1411 new ir.LetCont(rightFalseContinuation, | 1420 rightFalseContinuation], |
| 1412 new ir.Branch(new ir.IsTrue(rightValue), | 1421 new ir.Branch(new ir.IsTrue(rightValue), |
| 1413 rightTrueContinuation, | 1422 rightTrueContinuation, |
| 1414 rightFalseContinuation)))); | 1423 rightFalseContinuation))); |
| 1415 // Depending on the operator, the left subexpression's continuations are | 1424 // Depending on the operator, the left subexpression's continuations are |
| 1416 // either the right subexpression or an invocation of the join-point | 1425 // either the right subexpression or an invocation of the join-point |
| 1417 // continuation. | 1426 // continuation. |
| 1418 if (isLazyOr) { | 1427 if (isLazyOr) { |
| 1419 leftTrueContinuation.body = emptyBuilder._root; | 1428 leftTrueContinuation.body = emptyBuilder._root; |
| 1420 leftFalseContinuation.body = rightBuilder._root; | 1429 leftFalseContinuation.body = rightBuilder._root; |
| 1421 } else { | 1430 } else { |
| 1422 leftTrueContinuation.body = rightBuilder._root; | 1431 leftTrueContinuation.body = rightBuilder._root; |
| 1423 leftFalseContinuation.body = emptyBuilder._root; | 1432 leftFalseContinuation.body = emptyBuilder._root; |
| 1424 } | 1433 } |
| 1425 | 1434 |
| 1426 add(new ir.LetCont(joinContinuation, | 1435 add(new ir.LetCont(<ir.Continuation>[joinContinuation], |
| 1427 new ir.LetCont(leftTrueContinuation, | 1436 new ir.LetCont(<ir.Continuation>[leftTrueContinuation, |
| 1428 new ir.LetCont(leftFalseContinuation, | 1437 leftFalseContinuation], |
| 1429 new ir.Branch(new ir.IsTrue(leftValue), | 1438 new ir.Branch(new ir.IsTrue(leftValue), |
| 1430 leftTrueContinuation, | 1439 leftTrueContinuation, |
| 1431 leftFalseContinuation))))); | 1440 leftFalseContinuation)))); |
| 1432 // There is always a join parameter for the result value, because it | 1441 // There is always a join parameter for the result value, because it |
| 1433 // is different on at least two paths. | 1442 // is different on at least two paths. |
| 1434 return joinContinuation.parameters.last; | 1443 return joinContinuation.parameters.last; |
| 1435 } | 1444 } |
| 1436 | 1445 |
| 1437 /// Creates an access to the receiver from the current (or enclosing) method. | 1446 /// Creates an access to the receiver from the current (or enclosing) method. |
| 1438 /// | 1447 /// |
| 1439 /// If inside a closure class, [buildThis] will redirect access through | 1448 /// If inside a closure class, [buildThis] will redirect access through |
| 1440 /// closure fields in order to access the receiver from the enclosing method. | 1449 /// closure fields in order to access the receiver from the enclosing method. |
| 1441 ir.Primitive buildThis() { | 1450 ir.Primitive buildThis() { |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1876 | 1885 |
| 1877 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); | 1886 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); |
| 1878 } | 1887 } |
| 1879 | 1888 |
| 1880 /// Information about which variables are captured in a closure. | 1889 /// Information about which variables are captured in a closure. |
| 1881 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and | 1890 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and |
| 1882 /// [ClosureEnvironment]. | 1891 /// [ClosureEnvironment]. |
| 1883 abstract class ClosureVariableInfo { | 1892 abstract class ClosureVariableInfo { |
| 1884 Iterable<Local> get capturedVariables; | 1893 Iterable<Local> get capturedVariables; |
| 1885 } | 1894 } |
| OLD | NEW |