Chromium Code Reviews| 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 /// Eliminates moving assignments, such as w := v, by assigning directly to w | 7 /// Eliminates moving assignments, such as w := v, by assigning directly to w |
| 8 /// at the definition of v. | 8 /// at the definition of v. |
| 9 /// | 9 /// |
| 10 /// This compensates for suboptimal register allocation, and merges closure | 10 /// This compensates for suboptimal register allocation, and merges closure |
| 11 /// variables with local temporaries that were left behind when translating | 11 /// variables with local temporaries that were left behind when translating |
| 12 /// out of CPS (where closure variables live in a separate space). | 12 /// out of CPS (where closure variables live in a separate space). |
| 13 class CopyPropagator extends RecursiveVisitor with PassMixin { | 13 class CopyPropagator extends RecursiveVisitor with PassMixin { |
| 14 | 14 |
| 15 /// After visitStatement returns, [move] maps a variable v to an | 15 /// After visitStatement returns, [move] maps a variable v to an |
| 16 /// assignment A of form w := v, under the following conditions: | 16 /// assignment A of form w := v, under the following conditions: |
| 17 /// - there are no reads or writes of w before A | 17 /// - there are no reads or writes of w before A |
| 18 /// - A is the only use of v | 18 /// - A is the only use of v |
| 19 Map<Variable, Assign> move = <Variable, Assign>{}; | 19 Map<Variable, Assign> move = <Variable, Assign>{}; |
| 20 | 20 |
| 21 /// Like [move], except w is the key instead of v. | 21 /// Like [move], except w is the key instead of v. |
| 22 Map<Variable, Assign> inverseMove = <Variable, Assign>{}; | 22 Map<Variable, Assign> inverseMove = <Variable, Assign>{}; |
| 23 | 23 |
| 24 ExecutableElement currentElement; | 24 ExecutableElement currentElement; |
| 25 | 25 |
| 26 /// Number of try blocks enclosing the currently visited node. | |
| 27 int enclosingTrys = 0; | |
| 28 | |
| 26 void rewriteExecutableDefinition(ExecutableDefinition root) { | 29 void rewriteExecutableDefinition(ExecutableDefinition root) { |
| 27 currentElement = root.element; | 30 currentElement = root.element; |
| 28 root.body = visitStatement(root.body); | 31 root.body = visitStatement(root.body); |
| 29 } | 32 } |
| 30 | 33 |
| 31 rewriteFunctionDefinition(FunctionDefinition node) { | 34 rewriteFunctionDefinition(FunctionDefinition node) { |
| 32 if (node.isAbstract) return; | 35 if (node.isAbstract) return; |
| 33 rewriteExecutableDefinition(node); | 36 rewriteExecutableDefinition(node); |
| 34 | 37 |
| 35 // Try to propagate moving assignments into function parameters. | 38 // Try to propagate moving assignments into function parameters. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 161 node.variable = copyPropagateVariable(node.variable); | 164 node.variable = copyPropagateVariable(node.variable); |
| 162 | 165 |
| 163 // If a moving assignment w := v exists later, and we assign to w here, | 166 // If a moving assignment w := v exists later, and we assign to w here, |
| 164 // the moving assignment is no longer a candidate for copy propagation. | 167 // the moving assignment is no longer a candidate for copy propagation. |
| 165 invalidateMovingAssignment(node.variable); | 168 invalidateMovingAssignment(node.variable); |
| 166 | 169 |
| 167 visitExpression(node.definition); | 170 visitExpression(node.definition); |
| 168 | 171 |
| 169 // If this is a moving assignment w := v, with this being the only use of v, | 172 // If this is a moving assignment w := v, with this being the only use of v, |
| 170 // try to propagate it backwards. Do not propagate assignments where w | 173 // try to propagate it backwards. Do not propagate assignments where w |
| 171 // is from an outer function scope. | 174 // is captured or if where are inside a try block, because then we can't |
| 172 if (node.definition is VariableUse) { | 175 // isolate the uses of w to a given basic block. |
| 176 if (node.definition is VariableUse && !node.isDeclaration && | |
|
Kevin Millikin (Google)
2015/03/06 09:30:33
I think it's confusing to call this field Assign.d
asgerf
2015/03/06 10:01:37
It's been bothering me too. I'll rename it to .val
| |
| 177 !node.variable.isCaptured && enclosingTrys == 0) { | |
| 173 VariableUse definition = node.definition; | 178 VariableUse definition = node.definition; |
| 174 if (definition.variable.readCount == 1 && | 179 if (definition.variable.readCount == 1) { |
| 175 node.variable.host == currentElement) { | |
| 176 move[definition.variable] = node; | 180 move[definition.variable] = node; |
| 177 inverseMove[node.variable] = node; | 181 inverseMove[node.variable] = node; |
| 178 } | 182 } |
| 179 } | 183 } |
| 180 | 184 |
| 181 return node; | 185 return node; |
| 182 } | 186 } |
| 183 | 187 |
| 184 Statement visitLabeledStatement(LabeledStatement node) { | 188 Statement visitLabeledStatement(LabeledStatement node) { |
| 185 node.next = visitBasicBlock(node.next); | 189 node.next = visitBasicBlock(node.next); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 210 Statement visitWhileTrue(WhileTrue node) { | 214 Statement visitWhileTrue(WhileTrue node) { |
| 211 node.body = visitBasicBlock(node.body); | 215 node.body = visitBasicBlock(node.body); |
| 212 return node; | 216 return node; |
| 213 } | 217 } |
| 214 | 218 |
| 215 Statement visitWhileCondition(WhileCondition node) { | 219 Statement visitWhileCondition(WhileCondition node) { |
| 216 throw "WhileCondition before LoopRewriter"; | 220 throw "WhileCondition before LoopRewriter"; |
| 217 } | 221 } |
| 218 | 222 |
| 219 Statement visitTry(Try node) { | 223 Statement visitTry(Try node) { |
| 224 enclosingTrys++; | |
| 220 node.tryBody = visitBasicBlock(node.tryBody); | 225 node.tryBody = visitBasicBlock(node.tryBody); |
| 226 enclosingTrys--; | |
| 221 node.catchBody = visitBasicBlock(node.catchBody); | 227 node.catchBody = visitBasicBlock(node.catchBody); |
| 222 return node; | 228 return node; |
| 223 } | 229 } |
| 224 | 230 |
| 225 Statement visitFunctionDeclaration(FunctionDeclaration node) { | 231 Statement visitFunctionDeclaration(FunctionDeclaration node) { |
| 226 // Unlike var declarations, function declarations are not hoisted, so we | 232 // Unlike var declarations, function declarations are not hoisted, so we |
| 227 // can't do copy propagation of the variable. | 233 // can't do copy propagation of the variable. |
| 228 new CopyPropagator().rewrite(node.definition); | 234 new CopyPropagator().rewrite(node.definition); |
| 229 node.next = visitStatement(node.next); | 235 node.next = visitStatement(node.next); |
| 230 return node; | 236 return node; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 245 | 251 |
| 246 void visitFunctionExpression(FunctionExpression node) { | 252 void visitFunctionExpression(FunctionExpression node) { |
| 247 new CopyPropagator().rewrite(node.definition); | 253 new CopyPropagator().rewrite(node.definition); |
| 248 } | 254 } |
| 249 | 255 |
| 250 void visitFieldInitializer(FieldInitializer node) { | 256 void visitFieldInitializer(FieldInitializer node) { |
| 251 visitStatement(node.body); | 257 visitStatement(node.body); |
| 252 } | 258 } |
| 253 | 259 |
| 254 } | 260 } |
| OLD | NEW |