| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 part of tree_ir.optimization; | 5 part of tree_ir.optimization; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Performs the following transformations on the tree: | 8 * Performs the following transformations on the tree: |
| 9 * - Assignment propagation | 9 * - Assignment propagation |
| 10 * - If-to-conditional conversion | 10 * - If-to-conditional conversion |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 * to their label are redirected. | 84 * to their label are redirected. |
| 85 * For example, where 'jump' is either break or continue: | 85 * For example, where 'jump' is either break or continue: |
| 86 * | 86 * |
| 87 * L0: {... break L0 ...}; jump L1 | 87 * L0: {... break L0 ...}; jump L1 |
| 88 * ==> | 88 * ==> |
| 89 * {... jump L1 ...} | 89 * {... jump L1 ...} |
| 90 * | 90 * |
| 91 * This may trigger a flattening of nested ifs in case the eliminated label | 91 * This may trigger a flattening of nested ifs in case the eliminated label |
| 92 * separated two ifs. | 92 * separated two ifs. |
| 93 */ | 93 */ |
| 94 class StatementRewriter extends Visitor<Statement, Expression> with PassMixin { | 94 class StatementRewriter extends Transformer implements Pass { |
| 95 String get passName => 'Statement rewriter'; | 95 String get passName => 'Statement rewriter'; |
| 96 | 96 |
| 97 @override |
| 98 void rewrite(RootNode node) { |
| 99 node.replaceEachBody(visitStatement); |
| 100 } |
| 101 |
| 97 // The binding environment. The rightmost element of the list is the nearest | 102 // The binding environment. The rightmost element of the list is the nearest |
| 98 // available enclosing binding. | 103 // available enclosing binding. |
| 99 List<Assign> environment; | 104 List<Assign> environment = <Assign>[]; |
| 100 | 105 |
| 101 /// Binding environment for variables that are assigned to effectively | 106 /// Binding environment for variables that are assigned to effectively |
| 102 /// constant expressions (see [isEffectivelyConstant]). | 107 /// constant expressions (see [isEffectivelyConstant]). |
| 103 final Map<Variable, Expression> constantEnvironment; | 108 final Map<Variable, Expression> constantEnvironment; |
| 104 | 109 |
| 105 /// Substitution map for labels. Any break to a label L should be substituted | 110 /// Substitution map for labels. Any break to a label L should be substituted |
| 106 /// for a break to L' if L maps to L'. | 111 /// for a break to L' if L maps to L'. |
| 107 Map<Label, Jump> labelRedirects = <Label, Jump>{}; | 112 Map<Label, Jump> labelRedirects = <Label, Jump>{}; |
| 108 | 113 |
| 109 /// Rewriter for methods. | 114 /// Rewriter for methods. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 121 /// handler (i.e., if the code would be moved into a try from outside it). | 126 /// handler (i.e., if the code would be moved into a try from outside it). |
| 122 Set<Label> safeForInlining = new Set<Label>(); | 127 Set<Label> safeForInlining = new Set<Label>(); |
| 123 | 128 |
| 124 /// Returns the redirect target of [jump] or [jump] itself if it should not | 129 /// Returns the redirect target of [jump] or [jump] itself if it should not |
| 125 /// be redirected. | 130 /// be redirected. |
| 126 Jump redirect(Jump jump) { | 131 Jump redirect(Jump jump) { |
| 127 Jump newJump = labelRedirects[jump.target]; | 132 Jump newJump = labelRedirects[jump.target]; |
| 128 return newJump != null ? newJump : jump; | 133 return newJump != null ? newJump : jump; |
| 129 } | 134 } |
| 130 | 135 |
| 131 rewriteExecutableDefinition(ExecutableDefinition definition) { | |
| 132 inEmptyEnvironment(() { | |
| 133 definition.body = visitStatement(definition.body); | |
| 134 }); | |
| 135 } | |
| 136 | |
| 137 void rewriteConstructorDefinition(ConstructorDefinition definition) { | |
| 138 if (definition.isAbstract) return; | |
| 139 definition.initializers.forEach(visitExpression); | |
| 140 rewriteExecutableDefinition(definition); | |
| 141 } | |
| 142 | |
| 143 void inEmptyEnvironment(void action()) { | 136 void inEmptyEnvironment(void action()) { |
| 144 List<Assign> oldEnvironment = environment; | 137 List<Assign> oldEnvironment = environment; |
| 145 environment = <Assign>[]; | 138 environment = <Assign>[]; |
| 146 action(); | 139 action(); |
| 147 assert(environment.isEmpty); | 140 assert(environment.isEmpty); |
| 148 environment = oldEnvironment; | 141 environment = oldEnvironment; |
| 149 } | 142 } |
| 150 | 143 |
| 151 Expression visitFieldInitializer(FieldInitializer node) { | |
| 152 inEmptyEnvironment(() { | |
| 153 node.body = visitStatement(node.body); | |
| 154 }); | |
| 155 return node; | |
| 156 } | |
| 157 | |
| 158 Expression visitSuperInitializer(SuperInitializer node) { | |
| 159 inEmptyEnvironment(() { | |
| 160 for (int i = node.arguments.length - 1; i >= 0; --i) { | |
| 161 node.arguments[i] = visitStatement(node.arguments[i]); | |
| 162 assert(environment.isEmpty); | |
| 163 } | |
| 164 }); | |
| 165 return node; | |
| 166 } | |
| 167 | |
| 168 Expression visitExpression(Expression e) => e.processed ? e : e.accept(this); | 144 Expression visitExpression(Expression e) => e.processed ? e : e.accept(this); |
| 169 | 145 |
| 170 @override | 146 @override |
| 171 Expression visitVariableUse(VariableUse node) { | 147 Expression visitVariableUse(VariableUse node) { |
| 172 // Propagate constant to use site. | 148 // Propagate constant to use site. |
| 173 Expression constant = constantEnvironment[node.variable]; | 149 Expression constant = constantEnvironment[node.variable]; |
| 174 if (constant != null) { | 150 if (constant != null) { |
| 175 --node.variable.readCount; | 151 --node.variable.readCount; |
| 176 return constant; | 152 return constant; |
| 177 } | 153 } |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 } | 672 } |
| 697 | 673 |
| 698 Expression makeCondition(Expression e, bool polarity) { | 674 Expression makeCondition(Expression e, bool polarity) { |
| 699 return polarity ? e : new Not(e); | 675 return polarity ? e : new Not(e); |
| 700 } | 676 } |
| 701 | 677 |
| 702 Statement getBranch(If node, bool polarity) { | 678 Statement getBranch(If node, bool polarity) { |
| 703 return polarity ? node.thenStatement : node.elseStatement; | 679 return polarity ? node.thenStatement : node.elseStatement; |
| 704 } | 680 } |
| 705 } | 681 } |
| OLD | NEW |