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 /** | 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 */ | 93 */ |
| 94 class StatementRewriter extends Visitor<Statement, Expression> with PassMixin { | 94 class StatementRewriter extends Visitor<Statement, Expression> with PassMixin { |
| 95 // The binding environment. The rightmost element of the list is the nearest | 95 // The binding environment. The rightmost element of the list is the nearest |
| 96 // available enclosing binding. | 96 // available enclosing binding. |
| 97 List<Assign> environment; | 97 List<Assign> environment; |
| 98 | 98 |
| 99 /// Substitution map for labels. Any break to a label L should be substituted | 99 /// Substitution map for labels. Any break to a label L should be substituted |
| 100 /// for a break to L' if L maps to L'. | 100 /// for a break to L' if L maps to L'. |
| 101 Map<Label, Jump> labelRedirects = <Label, Jump>{}; | 101 Map<Label, Jump> labelRedirects = <Label, Jump>{}; |
| 102 | 102 |
| 103 /// Returns the redirect target of [label] or [label] itself if it should not | 103 // The successor statements for labeled statements that have only one break |
|
karlklose
2015/02/16 10:15:48
Use '///'.
| |
| 104 // from them are normally rewritten inline at the site of the break. This is | |
| 105 // not safe if the code would be move inside the scope of an exception | |
|
karlklose
2015/02/16 10:15:48
'move' -> 'moved'.
| |
| 106 // handler (i.e., if the code would be moved into a try from outside it. | |
|
karlklose
2015/02/16 10:15:48
Missing ')'.
Kevin Millikin (Google)
2015/02/25 11:06:36
That's embarassing for a Lisper.
| |
| 107 List<Label> safeForHandlers = <Label>[]; | |
| 108 | |
| 109 /// Returns the redirect target of [jump] or [jump] itself if it should not | |
| 104 /// be redirected. | 110 /// be redirected. |
| 105 Jump redirect(Jump jump) { | 111 Jump redirect(Jump jump) { |
| 106 Jump newJump = labelRedirects[jump.target]; | 112 Jump newJump = labelRedirects[jump.target]; |
| 107 return newJump != null ? newJump : jump; | 113 return newJump != null ? newJump : jump; |
| 108 } | 114 } |
| 109 | 115 |
| 110 | 116 |
| 111 rewriteExecutableDefinition(ExecutableDefinition definition) { | 117 rewriteExecutableDefinition(ExecutableDefinition definition) { |
| 112 definition.body = rewriteInEmptyEnvironment(definition.body); | 118 definition.body = rewriteInEmptyEnvironment(definition.body); |
| 113 } | 119 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 node.value = visitExpression(node.value); | 264 node.value = visitExpression(node.value); |
| 259 return node; | 265 return node; |
| 260 } | 266 } |
| 261 | 267 |
| 262 | 268 |
| 263 Statement visitBreak(Break node) { | 269 Statement visitBreak(Break node) { |
| 264 // Redirect through chain of breaks. | 270 // Redirect through chain of breaks. |
| 265 // Note that useCount was accounted for at visitLabeledStatement. | 271 // Note that useCount was accounted for at visitLabeledStatement. |
| 266 // Note redirect may return either a Break or Continue statement. | 272 // Note redirect may return either a Break or Continue statement. |
| 267 Jump jump = redirect(node); | 273 Jump jump = redirect(node); |
| 268 if (jump is Break && jump.target.useCount == 1) { | 274 if (jump is Break && |
| 275 jump.target.useCount == 1 && | |
| 276 safeForHandlers.contains(jump.target)) { | |
|
asgerf
2015/02/20 10:10:07
Isn't this a bit expensive? It looks like a quadra
Kevin Millikin (Google)
2015/02/25 11:06:36
I don't think it's best to add only singly-used la
asgerf
2015/02/25 11:55:11
Ah, I forgot the use-counts on labels change durin
| |
| 269 --jump.target.useCount; | 277 --jump.target.useCount; |
| 270 return visitStatement(jump.target.binding.next); | 278 return visitStatement(jump.target.binding.next); |
| 271 } | 279 } |
| 272 return jump; | 280 return jump; |
| 273 } | 281 } |
| 274 | 282 |
| 275 Statement visitContinue(Continue node) { | 283 Statement visitContinue(Continue node) { |
| 276 return node; | 284 return node; |
| 277 } | 285 } |
| 278 | 286 |
| 279 Statement visitLabeledStatement(LabeledStatement node) { | 287 Statement visitLabeledStatement(LabeledStatement node) { |
| 280 if (node.next is Jump) { | 288 if (node.next is Jump) { |
| 281 // Eliminate label if next is a break or continue statement | 289 // Eliminate label if next is a break or continue statement |
| 282 // Breaks to this label are redirected to the outer label. | 290 // Breaks to this label are redirected to the outer label. |
| 283 // Note that breakCount for the two labels is updated proactively here | 291 // Note that breakCount for the two labels is updated proactively here |
| 284 // so breaks can reliably tell if they should inline their target. | 292 // so breaks can reliably tell if they should inline their target. |
| 285 Jump next = node.next; | 293 Jump next = node.next; |
| 286 Jump newJump = redirect(next); | 294 Jump newJump = redirect(next); |
| 287 labelRedirects[node.label] = newJump; | 295 labelRedirects[node.label] = newJump; |
| 288 newJump.target.useCount += node.label.useCount - 1; | 296 newJump.target.useCount += node.label.useCount - 1; |
| 289 node.label.useCount = 0; | 297 node.label.useCount = 0; |
| 290 Statement result = visitStatement(node.body); | 298 Statement result = visitStatement(node.body); |
| 291 labelRedirects.remove(node.label); // Save some space. | 299 labelRedirects.remove(node.label); // Save some space. |
| 292 return result; | 300 return result; |
| 293 } | 301 } |
| 294 | 302 |
| 303 safeForHandlers.add(node.label); | |
| 295 node.body = visitStatement(node.body); | 304 node.body = visitStatement(node.body); |
| 305 safeForHandlers.removeLast(); | |
| 296 | 306 |
| 297 if (node.label.useCount == 0) { | 307 if (node.label.useCount == 0) { |
| 298 // Eliminate the label if next was inlined at a break | 308 // Eliminate the label if next was inlined at a break |
| 299 return node.body; | 309 return node.body; |
| 300 } | 310 } |
| 301 | 311 |
| 302 // Do not propagate assignments into the successor statements, since they | 312 // Do not propagate assignments into the successor statements, since they |
| 303 // may be overwritten by assignments in the body. | 313 // may be overwritten by assignments in the body. |
| 304 List<Assign> savedEnvironment = environment; | 314 List<Assign> savedEnvironment = environment; |
| 305 environment = <Assign>[]; | 315 environment = <Assign>[]; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 351 assert(environment.isEmpty); | 361 assert(environment.isEmpty); |
| 352 environment = savedEnvironment; | 362 environment = savedEnvironment; |
| 353 return node; | 363 return node; |
| 354 } | 364 } |
| 355 | 365 |
| 356 Statement visitWhileCondition(WhileCondition node) { | 366 Statement visitWhileCondition(WhileCondition node) { |
| 357 // Not introduced yet | 367 // Not introduced yet |
| 358 throw "Unexpected WhileCondition in StatementRewriter"; | 368 throw "Unexpected WhileCondition in StatementRewriter"; |
| 359 } | 369 } |
| 360 | 370 |
| 371 Statement visitTryStatement(TryStatement node) { | |
| 372 List<Label> saved = safeForHandlers; | |
| 373 safeForHandlers = <Label>[]; | |
| 374 node.tryBody = visitStatement(node.tryBody); | |
| 375 safeForHandlers = saved; | |
| 376 node.catchBody = visitStatement(node.catchBody); | |
| 377 return node; | |
| 378 } | |
| 379 | |
| 361 Expression visitConstant(Constant node) { | 380 Expression visitConstant(Constant node) { |
| 362 return node; | 381 return node; |
| 363 } | 382 } |
| 364 | 383 |
| 365 Expression visitThis(This node) { | 384 Expression visitThis(This node) { |
| 366 return node; | 385 return node; |
| 367 } | 386 } |
| 368 | 387 |
| 369 Expression visitReifyTypeVar(ReifyTypeVar node) { | 388 Expression visitReifyTypeVar(ReifyTypeVar node) { |
| 370 return node; | 389 return node; |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 } | 609 } |
| 591 | 610 |
| 592 Expression makeCondition(Expression e, bool polarity) { | 611 Expression makeCondition(Expression e, bool polarity) { |
| 593 return polarity ? e : new Not(e); | 612 return polarity ? e : new Not(e); |
| 594 } | 613 } |
| 595 | 614 |
| 596 Statement getBranch(If node, bool polarity) { | 615 Statement getBranch(If node, bool polarity) { |
| 597 return polarity ? node.thenStatement : node.elseStatement; | 616 return polarity ? node.thenStatement : node.elseStatement; |
| 598 } | 617 } |
| 599 } | 618 } |
| OLD | NEW |