| 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 /// for a break to L' if L maps to L'. | 104 /// for a break to L' if L maps to L'. |
| 105 Map<Label, Jump> labelRedirects = <Label, Jump>{}; | 105 Map<Label, Jump> labelRedirects = <Label, Jump>{}; |
| 106 | 106 |
| 107 /// Rewriter for methods. | 107 /// Rewriter for methods. |
| 108 StatementRewriter() : constantEnvironment = <Variable, Expression>{}; | 108 StatementRewriter() : constantEnvironment = <Variable, Expression>{}; |
| 109 | 109 |
| 110 /// Rewriter for nested functions. | 110 /// Rewriter for nested functions. |
| 111 StatementRewriter.nested(StatementRewriter parent) | 111 StatementRewriter.nested(StatementRewriter parent) |
| 112 : constantEnvironment = parent.constantEnvironment; | 112 : constantEnvironment = parent.constantEnvironment; |
| 113 | 113 |
| 114 /// Returns the redirect target of [label] or [label] itself if it should not | 114 /// A set of labels that can be safely inlined at their use. |
| 115 /// |
| 116 /// The successor statements for labeled statements that have only one break |
| 117 /// from them are normally rewritten inline at the site of the break. This |
| 118 /// is not safe if the code would be moved inside the scope of an exception |
| 119 /// handler (i.e., if the code would be moved into a try from outside it). |
| 120 Set<Label> safeForInlining = new Set<Label>(); |
| 121 |
| 122 /// Returns the redirect target of [jump] or [jump] itself if it should not |
| 115 /// be redirected. | 123 /// be redirected. |
| 116 Jump redirect(Jump jump) { | 124 Jump redirect(Jump jump) { |
| 117 Jump newJump = labelRedirects[jump.target]; | 125 Jump newJump = labelRedirects[jump.target]; |
| 118 return newJump != null ? newJump : jump; | 126 return newJump != null ? newJump : jump; |
| 119 } | 127 } |
| 120 | 128 |
| 121 rewriteExecutableDefinition(ExecutableDefinition definition) { | 129 rewriteExecutableDefinition(ExecutableDefinition definition) { |
| 122 inEmptyEnvironment(() { | 130 inEmptyEnvironment(() { |
| 123 definition.body = visitStatement(definition.body); | 131 definition.body = visitStatement(definition.body); |
| 124 }); | 132 }); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 node.value = visitExpression(node.value); | 311 node.value = visitExpression(node.value); |
| 304 return node; | 312 return node; |
| 305 } | 313 } |
| 306 | 314 |
| 307 | 315 |
| 308 Statement visitBreak(Break node) { | 316 Statement visitBreak(Break node) { |
| 309 // Redirect through chain of breaks. | 317 // Redirect through chain of breaks. |
| 310 // Note that useCount was accounted for at visitLabeledStatement. | 318 // Note that useCount was accounted for at visitLabeledStatement. |
| 311 // Note redirect may return either a Break or Continue statement. | 319 // Note redirect may return either a Break or Continue statement. |
| 312 Jump jump = redirect(node); | 320 Jump jump = redirect(node); |
| 313 if (jump is Break && jump.target.useCount == 1) { | 321 if (jump is Break && |
| 322 jump.target.useCount == 1 && |
| 323 safeForInlining.contains(jump.target)) { |
| 314 --jump.target.useCount; | 324 --jump.target.useCount; |
| 315 return visitStatement(jump.target.binding.next); | 325 return visitStatement(jump.target.binding.next); |
| 316 } | 326 } |
| 317 return jump; | 327 return jump; |
| 318 } | 328 } |
| 319 | 329 |
| 320 Statement visitContinue(Continue node) { | 330 Statement visitContinue(Continue node) { |
| 321 return node; | 331 return node; |
| 322 } | 332 } |
| 323 | 333 |
| 324 Statement visitLabeledStatement(LabeledStatement node) { | 334 Statement visitLabeledStatement(LabeledStatement node) { |
| 325 if (node.next is Jump) { | 335 if (node.next is Jump) { |
| 326 // Eliminate label if next is a break or continue statement | 336 // Eliminate label if next is a break or continue statement |
| 327 // Breaks to this label are redirected to the outer label. | 337 // Breaks to this label are redirected to the outer label. |
| 328 // Note that breakCount for the two labels is updated proactively here | 338 // Note that breakCount for the two labels is updated proactively here |
| 329 // so breaks can reliably tell if they should inline their target. | 339 // so breaks can reliably tell if they should inline their target. |
| 330 Jump next = node.next; | 340 Jump next = node.next; |
| 331 Jump newJump = redirect(next); | 341 Jump newJump = redirect(next); |
| 332 labelRedirects[node.label] = newJump; | 342 labelRedirects[node.label] = newJump; |
| 333 newJump.target.useCount += node.label.useCount - 1; | 343 newJump.target.useCount += node.label.useCount - 1; |
| 334 node.label.useCount = 0; | 344 node.label.useCount = 0; |
| 335 Statement result = visitStatement(node.body); | 345 Statement result = visitStatement(node.body); |
| 336 labelRedirects.remove(node.label); // Save some space. | 346 labelRedirects.remove(node.label); // Save some space. |
| 337 return result; | 347 return result; |
| 338 } | 348 } |
| 339 | 349 |
| 350 safeForInlining.add(node.label); |
| 340 node.body = visitStatement(node.body); | 351 node.body = visitStatement(node.body); |
| 352 safeForInlining.remove(node.label); |
| 341 | 353 |
| 342 if (node.label.useCount == 0) { | 354 if (node.label.useCount == 0) { |
| 343 // Eliminate the label if next was inlined at a break | 355 // Eliminate the label if next was inlined at a break |
| 344 return node.body; | 356 return node.body; |
| 345 } | 357 } |
| 346 | 358 |
| 347 // Do not propagate assignments into the successor statements, since they | 359 // Do not propagate assignments into the successor statements, since they |
| 348 // may be overwritten by assignments in the body. | 360 // may be overwritten by assignments in the body. |
| 349 inEmptyEnvironment(() { | 361 inEmptyEnvironment(() { |
| 350 node.next = visitStatement(node.next); | 362 node.next = visitStatement(node.next); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 node.body = visitStatement(node.body); | 402 node.body = visitStatement(node.body); |
| 391 }); | 403 }); |
| 392 return node; | 404 return node; |
| 393 } | 405 } |
| 394 | 406 |
| 395 Statement visitWhileCondition(WhileCondition node) { | 407 Statement visitWhileCondition(WhileCondition node) { |
| 396 // Not introduced yet | 408 // Not introduced yet |
| 397 throw "Unexpected WhileCondition in StatementRewriter"; | 409 throw "Unexpected WhileCondition in StatementRewriter"; |
| 398 } | 410 } |
| 399 | 411 |
| 412 Statement visitTry(Try node) { |
| 413 Set<Label> saved = safeForInlining; |
| 414 safeForInlining = new Set<Label>(); |
| 415 node.tryBody = visitStatement(node.tryBody); |
| 416 safeForInlining = saved; |
| 417 node.catchBody = visitStatement(node.catchBody); |
| 418 return node; |
| 419 } |
| 420 |
| 400 Expression visitConstant(Constant node) { | 421 Expression visitConstant(Constant node) { |
| 401 return node; | 422 return node; |
| 402 } | 423 } |
| 403 | 424 |
| 404 Expression visitThis(This node) { | 425 Expression visitThis(This node) { |
| 405 return node; | 426 return node; |
| 406 } | 427 } |
| 407 | 428 |
| 408 Expression visitReifyTypeVar(ReifyTypeVar node) { | 429 Expression visitReifyTypeVar(ReifyTypeVar node) { |
| 409 return node; | 430 return node; |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 } | 646 } |
| 626 | 647 |
| 627 Expression makeCondition(Expression e, bool polarity) { | 648 Expression makeCondition(Expression e, bool polarity) { |
| 628 return polarity ? e : new Not(e); | 649 return polarity ? e : new Not(e); |
| 629 } | 650 } |
| 630 | 651 |
| 631 Statement getBranch(If node, bool polarity) { | 652 Statement getBranch(If node, bool polarity) { |
| 632 return polarity ? node.thenStatement : node.elseStatement; | 653 return polarity ? node.thenStatement : node.elseStatement; |
| 633 } | 654 } |
| 634 } | 655 } |
| OLD | NEW |