| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 tree_ir.optimization.variable_merger; | 5 library tree_ir.optimization.variable_merger; |
| 6 | 6 |
| 7 import 'optimization.dart' show Pass, PassMixin; | 7 import 'optimization.dart' show Pass; |
| 8 import '../tree_ir_nodes.dart'; | 8 import '../tree_ir_nodes.dart'; |
| 9 import '../../elements/elements.dart' show Local, ParameterElement; | 9 import '../../elements/elements.dart' show Local, ParameterElement; |
| 10 | 10 |
| 11 /// Merges variables based on liveness and source variable information. | 11 /// Merges variables based on liveness and source variable information. |
| 12 /// | 12 /// |
| 13 /// This phase cleans up artifacts introduced by the translation through CPS, | 13 /// This phase cleans up artifacts introduced by the translation through CPS, |
| 14 /// where each source variable is translated into several copies. The copies | 14 /// where each source variable is translated into several copies. The copies |
| 15 /// are merged again when they are not live simultaneously. | 15 /// are merged again when they are not live simultaneously. |
| 16 class VariableMerger extends RecursiveVisitor implements Pass { | 16 class VariableMerger extends RecursiveVisitor implements Pass { |
| 17 String get passName => 'Variable merger'; | 17 String get passName => 'Variable merger'; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 /// be excluded from the control-flow graph. | 158 /// be excluded from the control-flow graph. |
| 159 /// Subsequent calls to [read] and [write] will ignore it. | 159 /// Subsequent calls to [read] and [write] will ignore it. |
| 160 void ignoreVariable(Variable variable) { | 160 void ignoreVariable(Variable variable) { |
| 161 _ignoredVariables.add(variable); | 161 _ignoredVariables.add(variable); |
| 162 } | 162 } |
| 163 | 163 |
| 164 visitVariableUse(VariableUse node) { | 164 visitVariableUse(VariableUse node) { |
| 165 read(node.variable); | 165 read(node.variable); |
| 166 } | 166 } |
| 167 | 167 |
| 168 visitVariableDeclaration(VariableDeclaration node) { |
| 169 assert(node.variable.isCaptured); |
| 170 visitStatement(node.next); |
| 171 } |
| 172 |
| 168 visitAssign(Assign node) { | 173 visitAssign(Assign node) { |
| 169 visitExpression(node.value); | 174 visitExpression(node.value); |
| 170 write(node.variable); | 175 write(node.variable); |
| 171 visitStatement(node.next); | |
| 172 } | 176 } |
| 173 | 177 |
| 174 visitIf(If node) { | 178 visitIf(If node) { |
| 175 visitExpression(node.condition); | 179 visitExpression(node.condition); |
| 176 Block afterCondition = _currentBlock; | 180 Block afterCondition = _currentBlock; |
| 177 branchFrom(afterCondition); | 181 branchFrom(afterCondition); |
| 178 visitStatement(node.thenStatement); | 182 visitStatement(node.thenStatement); |
| 179 branchFrom(afterCondition); | 183 branchFrom(afterCondition); |
| 180 visitStatement(node.elseStatement); | 184 visitStatement(node.elseStatement); |
| 181 } | 185 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 visitStatement(node.tryBody); | 224 visitStatement(node.tryBody); |
| 221 _currentBlock = catchBlock; | 225 _currentBlock = catchBlock; |
| 222 // Catch parameters cannot be hoisted to the top of the function, so to | 226 // Catch parameters cannot be hoisted to the top of the function, so to |
| 223 // avoid complications with scoping, we do not attempt to merge them. | 227 // avoid complications with scoping, we do not attempt to merge them. |
| 224 node.catchParameters.forEach(ignoreVariable); | 228 node.catchParameters.forEach(ignoreVariable); |
| 225 visitStatement(node.catchBody); | 229 visitStatement(node.catchBody); |
| 226 } | 230 } |
| 227 | 231 |
| 228 visitConditional(Conditional node) { | 232 visitConditional(Conditional node) { |
| 229 visitExpression(node.condition); | 233 visitExpression(node.condition); |
| 230 // TODO(asgerf): When assignment expressions are added, this is no longer | 234 Block afterCondition = _currentBlock; |
| 231 // sound; then we need to handle as a branch. | 235 branchFrom(afterCondition); |
| 232 visitExpression(node.thenExpression); | 236 visitExpression(node.thenExpression); |
| 237 branchFrom(afterCondition); |
| 233 visitExpression(node.elseExpression); | 238 visitExpression(node.elseExpression); |
| 234 } | 239 } |
| 235 | 240 |
| 236 visitLogicalOperator(LogicalOperator node) { | 241 visitLogicalOperator(LogicalOperator node) { |
| 237 visitExpression(node.left); | 242 visitExpression(node.left); |
| 238 // TODO(asgerf): When assignment expressions are added, this is no longer | 243 Block afterCondition = _currentBlock; |
| 239 // sound; then we need to handle as a branch. | 244 branchFrom(afterCondition); |
| 240 visitExpression(node.right); | 245 visitExpression(node.right); |
| 241 } | 246 } |
| 242 | 247 |
| 243 visitFunctionDeclaration(FunctionDeclaration node) { | 248 visitFunctionDeclaration(FunctionDeclaration node) { |
| 244 // The function variable is final, hence cannot be merged. | 249 // The function variable is final, hence cannot be merged. |
| 245 ignoreVariable(node.variable); | 250 ignoreVariable(node.variable); |
| 246 visitStatement(node.next); | 251 visitStatement(node.next); |
| 247 } | 252 } |
| 248 } | 253 } |
| 249 | 254 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 @override | 491 @override |
| 487 void visitInnerFunction(FunctionDefinition node) { | 492 void visitInnerFunction(FunctionDefinition node) { |
| 488 // Do nothing. Inner functions are traversed in VariableMerger. | 493 // Do nothing. Inner functions are traversed in VariableMerger. |
| 489 } | 494 } |
| 490 | 495 |
| 491 Expression visitVariableUse(VariableUse node) { | 496 Expression visitVariableUse(VariableUse node) { |
| 492 node.variable = replaceRead(node.variable); | 497 node.variable = replaceRead(node.variable); |
| 493 return node; | 498 return node; |
| 494 } | 499 } |
| 495 | 500 |
| 496 Statement visitAssign(Assign node) { | 501 Expression visitAssign(Assign node) { |
| 497 node.variable = replaceWrite(node.variable); | 502 node.variable = replaceWrite(node.variable); |
| 498 | 503 node.value = visitExpression(node.value); |
| 499 visitExpression(node.value); | |
| 500 node.next = visitStatement(node.next); | |
| 501 | 504 |
| 502 // Remove assignments of form "x := x" | 505 // Remove assignments of form "x := x" |
| 503 if (node.value is VariableUse) { | 506 if (node.value is VariableUse) { |
| 504 VariableUse value = node.value; | 507 VariableUse value = node.value; |
| 505 if (value.variable == node.variable) { | 508 if (value.variable == node.variable) { |
| 506 value.variable.readCount--; | 509 --node.variable.writeCount; |
| 507 node.variable.writeCount--; | 510 return value; |
| 508 return node.next; | |
| 509 } | 511 } |
| 510 } | 512 } |
| 511 | 513 |
| 512 return node; | 514 return node; |
| 513 } | 515 } |
| 516 |
| 517 Statement visitExpressionStatement(ExpressionStatement node) { |
| 518 node.expression = visitExpression(node.expression); |
| 519 node.next = visitStatement(node.next); |
| 520 if (node.expression is VariableUse) { |
| 521 VariableUse use = node.expression; |
| 522 --use.variable.readCount; |
| 523 return node.next; |
| 524 } |
| 525 return node; |
| 526 } |
| 527 |
| 528 Statement visitVariableDeclaration(VariableDeclaration node) { |
| 529 // VariableDeclaration is only used for captured variables, which are never |
| 530 // merged, so this is not strictly necessary. But it's nicer if this class |
| 531 // works for arbitrary substitution maps. |
| 532 node.variable = replaceWrite(node.variable); |
| 533 node.value = visitExpression(node.value); |
| 534 node.next = visitStatement(node.next); |
| 535 return node; |
| 536 } |
| 537 |
| 514 } | 538 } |
| OLD | NEW |