| 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 library tree_ir.optimization.statement_rewriter; |
| 6 |
| 7 import 'optimization.dart' show Pass; |
| 8 import '../tree_ir_nodes.dart'; |
| 6 | 9 |
| 7 /** | 10 /** |
| 8 * Performs the following transformations on the tree: | 11 * Performs the following transformations on the tree: |
| 9 * - Assignment inlining | 12 * - Assignment inlining |
| 10 * - Assignment expression propagation | 13 * - Assignment expression propagation |
| 11 * - If-to-conditional conversion | 14 * - If-to-conditional conversion |
| 12 * - Flatten nested ifs | 15 * - Flatten nested ifs |
| 13 * - Break inlining | 16 * - Break inlining |
| 14 * - Redirect breaks | 17 * - Redirect breaks |
| 15 * | 18 * |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 * ==> | 105 * ==> |
| 103 * {... jump L1 ...} | 106 * {... jump L1 ...} |
| 104 * | 107 * |
| 105 * This may trigger a flattening of nested ifs in case the eliminated label | 108 * This may trigger a flattening of nested ifs in case the eliminated label |
| 106 * separated two ifs. | 109 * separated two ifs. |
| 107 */ | 110 */ |
| 108 class StatementRewriter extends Transformer implements Pass { | 111 class StatementRewriter extends Transformer implements Pass { |
| 109 String get passName => 'Statement rewriter'; | 112 String get passName => 'Statement rewriter'; |
| 110 | 113 |
| 111 @override | 114 @override |
| 112 void rewrite(RootNode node) { | 115 void rewrite(FunctionDefinition node) { |
| 113 node.replaceEachBody(visitStatement); | 116 node.body = visitStatement(node.body); |
| 114 } | 117 } |
| 115 | 118 |
| 116 /// True if targeting Dart. | 119 /// True if targeting Dart. |
| 117 final bool isDartMode; | 120 final bool isDartMode; |
| 118 | 121 |
| 119 /// The most recently evaluated impure expressions, with the most recent | 122 /// The most recently evaluated impure expressions, with the most recent |
| 120 /// expression being last. | 123 /// expression being last. |
| 121 /// | 124 /// |
| 122 /// Most importantly, this contains [Assign] expressions that we attempt to | 125 /// Most importantly, this contains [Assign] expressions that we attempt to |
| 123 /// inline at their use site. It also contains other impure expressions that | 126 /// inline at their use site. It also contains other impure expressions that |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 } | 265 } |
| 263 | 266 |
| 264 /// Returns true if [exp] has no side effects and has a constant value within | 267 /// Returns true if [exp] has no side effects and has a constant value within |
| 265 /// any given activation of the enclosing method. | 268 /// any given activation of the enclosing method. |
| 266 bool isEffectivelyConstant(Expression exp) { | 269 bool isEffectivelyConstant(Expression exp) { |
| 267 // TODO(asgerf): Can be made more aggressive e.g. by checking conditional | 270 // TODO(asgerf): Can be made more aggressive e.g. by checking conditional |
| 268 // expressions recursively. Determine if that is a valuable optimization | 271 // expressions recursively. Determine if that is a valuable optimization |
| 269 // and/or if it is better handled at the CPS level. | 272 // and/or if it is better handled at the CPS level. |
| 270 return exp is Constant || | 273 return exp is Constant || |
| 271 exp is This || | 274 exp is This || |
| 272 exp is ReifyTypeVar || | |
| 273 exp is CreateInvocationMirror || | 275 exp is CreateInvocationMirror || |
| 274 exp is InvokeStatic && exp.isEffectivelyConstant || | 276 exp is InvokeStatic && exp.isEffectivelyConstant || |
| 275 exp is VariableUse && constantEnvironment.containsKey(exp.variable); | 277 exp is VariableUse && constantEnvironment.containsKey(exp.variable); |
| 276 } | 278 } |
| 277 | 279 |
| 278 /// True if [node] is an assignment that can be propagated as a constant. | 280 /// True if [node] is an assignment that can be propagated as a constant. |
| 279 bool isEffectivelyConstantAssignment(Expression node) { | 281 bool isEffectivelyConstantAssignment(Expression node) { |
| 280 return node is Assign && | 282 return node is Assign && |
| 281 node.variable.writeCount == 1 && | 283 node.variable.writeCount == 1 && |
| 282 isEffectivelyConstant(node.value); | 284 isEffectivelyConstant(node.value); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 // | 326 // |
| 325 // { x = foo(); bar(x) } ==> bar(x = foo()) ==> bar(foo()) | 327 // { x = foo(); bar(x) } ==> bar(x = foo()) ==> bar(foo()) |
| 326 // | 328 // |
| 327 if (node.variable.readCount == 0) { | 329 if (node.variable.readCount == 0) { |
| 328 --node.variable.writeCount; | 330 --node.variable.writeCount; |
| 329 return node.value; | 331 return node.value; |
| 330 } | 332 } |
| 331 return node; | 333 return node; |
| 332 } | 334 } |
| 333 | 335 |
| 334 Statement visitVariableDeclaration(VariableDeclaration node) { | |
| 335 if (isEffectivelyConstant(node.value)) { | |
| 336 node.next = visitStatement(node.next); | |
| 337 } else { | |
| 338 inEmptyEnvironment(() { | |
| 339 node.next = visitStatement(node.next); | |
| 340 }); | |
| 341 } | |
| 342 node.value = visitExpression(node.value); | |
| 343 return node; | |
| 344 } | |
| 345 | |
| 346 /// Process nodes right-to-left, the opposite of evaluation order in the case | 336 /// Process nodes right-to-left, the opposite of evaluation order in the case |
| 347 /// of argument lists.. | 337 /// of argument lists.. |
| 348 void _rewriteList(List<Node> nodes) { | 338 void _rewriteList(List<Node> nodes) { |
| 349 for (int i = nodes.length - 1; i >= 0; --i) { | 339 for (int i = nodes.length - 1; i >= 0; --i) { |
| 350 nodes[i] = visitExpression(nodes[i]); | 340 nodes[i] = visitExpression(nodes[i]); |
| 351 } | 341 } |
| 352 } | 342 } |
| 353 | 343 |
| 354 Expression visitInvokeStatic(InvokeStatic node) { | 344 Expression visitInvokeStatic(InvokeStatic node) { |
| 355 _rewriteList(node.arguments); | 345 _rewriteList(node.arguments); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 Expression visitNot(Not node) { | 405 Expression visitNot(Not node) { |
| 416 node.operand = visitExpression(node.operand); | 406 node.operand = visitExpression(node.operand); |
| 417 return node; | 407 return node; |
| 418 } | 408 } |
| 419 | 409 |
| 420 Expression visitFunctionExpression(FunctionExpression node) { | 410 Expression visitFunctionExpression(FunctionExpression node) { |
| 421 new StatementRewriter.nested(this).rewrite(node.definition); | 411 new StatementRewriter.nested(this).rewrite(node.definition); |
| 422 return node; | 412 return node; |
| 423 } | 413 } |
| 424 | 414 |
| 425 Statement visitFunctionDeclaration(FunctionDeclaration node) { | |
| 426 new StatementRewriter.nested(this).rewrite(node.definition); | |
| 427 node.next = visitStatement(node.next); | |
| 428 return node; | |
| 429 } | |
| 430 | |
| 431 Statement visitReturn(Return node) { | 415 Statement visitReturn(Return node) { |
| 432 node.value = visitExpression(node.value); | 416 node.value = visitExpression(node.value); |
| 433 return node; | 417 return node; |
| 434 } | 418 } |
| 435 | 419 |
| 436 Statement visitThrow(Throw node) { | 420 Statement visitThrow(Throw node) { |
| 437 node.value = visitExpression(node.value); | 421 node.value = visitExpression(node.value); |
| 438 return node; | 422 return node; |
| 439 } | 423 } |
| 440 | 424 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 } | 530 } |
| 547 | 531 |
| 548 Expression visitConstant(Constant node) { | 532 Expression visitConstant(Constant node) { |
| 549 return node; | 533 return node; |
| 550 } | 534 } |
| 551 | 535 |
| 552 Expression visitThis(This node) { | 536 Expression visitThis(This node) { |
| 553 return node; | 537 return node; |
| 554 } | 538 } |
| 555 | 539 |
| 556 Expression visitReifyTypeVar(ReifyTypeVar node) { | |
| 557 return node; | |
| 558 } | |
| 559 | |
| 560 Expression visitLiteralList(LiteralList node) { | 540 Expression visitLiteralList(LiteralList node) { |
| 561 _rewriteList(node.values); | 541 _rewriteList(node.values); |
| 562 return node; | 542 return node; |
| 563 } | 543 } |
| 564 | 544 |
| 565 Expression visitLiteralMap(LiteralMap node) { | 545 Expression visitLiteralMap(LiteralMap node) { |
| 566 // Process arguments right-to-left, the opposite of evaluation order. | 546 // Process arguments right-to-left, the opposite of evaluation order. |
| 567 for (LiteralMapEntry entry in node.entries.reversed) { | 547 for (LiteralMapEntry entry in node.entries.reversed) { |
| 568 entry.value = visitExpression(entry.value); | 548 entry.value = visitExpression(entry.value); |
| 569 entry.key = visitExpression(entry.key); | 549 entry.key = visitExpression(entry.key); |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 } | 903 } |
| 924 | 904 |
| 925 /// Result of combining two expressions that do not affect reference counting. | 905 /// Result of combining two expressions that do not affect reference counting. |
| 926 class GenericCombinedExpressions implements CombinedExpressions { | 906 class GenericCombinedExpressions implements CombinedExpressions { |
| 927 Expression combined; | 907 Expression combined; |
| 928 | 908 |
| 929 GenericCombinedExpressions(this.combined); | 909 GenericCombinedExpressions(this.combined); |
| 930 | 910 |
| 931 void uncombine() {} | 911 void uncombine() {} |
| 932 } | 912 } |
| OLD | NEW |