| 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 dart2js.cps_ir.optimizers; | 5 part of dart2js.cps_ir.optimizers; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * [ShrinkingReducer] applies shrinking reductions to CPS terms as described | 8 * [ShrinkingReducer] applies shrinking reductions to CPS terms as described |
| 9 * in 'Compiling with Continuations, Continued' by Andrew Kennedy. | 9 * in 'Compiling with Continuations, Continued' by Andrew Kennedy. |
| 10 */ | 10 */ |
| 11 class ShrinkingReducer extends PassMixin { | 11 class ShrinkingReducer extends Pass { |
| 12 String get passName => 'Shrinking reductions'; | 12 String get passName => 'Shrinking reductions'; |
| 13 | 13 |
| 14 Set<_ReductionTask> _worklist; | 14 Set<_ReductionTask> _worklist; |
| 15 | 15 |
| 16 static final _DeletedNode _DELETED = new _DeletedNode(); | 16 static final _DeletedNode _DELETED = new _DeletedNode(); |
| 17 | 17 |
| 18 /// Applies shrinking reductions to root, mutating root in the process. | 18 /// Applies shrinking reductions to root, mutating root in the process. |
| 19 @override | 19 @override |
| 20 void rewriteExecutableDefinition(ExecutableDefinition root) { | 20 void rewrite(RootNode root) { |
| 21 if (root.isEmpty) return; |
| 22 |
| 21 _worklist = new Set<_ReductionTask>(); | 23 _worklist = new Set<_ReductionTask>(); |
| 22 _RedexVisitor redexVisitor = new _RedexVisitor(_worklist); | 24 _RedexVisitor redexVisitor = new _RedexVisitor(_worklist); |
| 23 | 25 |
| 24 // Set all parent pointers. | 26 // Set all parent pointers. |
| 25 new ParentVisitor().visit(root); | 27 new ParentVisitor().visit(root); |
| 26 | 28 |
| 27 // Sweep over the term, collecting redexes into the worklist. | 29 // Sweep over the term, collecting redexes into the worklist. |
| 28 redexVisitor.visit(root); | 30 redexVisitor.visit(root); |
| 29 | 31 |
| 30 // Process the worklist. | 32 // Process the worklist. |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 Node parent = primitive.parent; | 459 Node parent = primitive.parent; |
| 458 // The parent might be the deleted sentinel, or it might be a | 460 // The parent might be the deleted sentinel, or it might be a |
| 459 // Continuation or FunctionDefinition if the primitive is an argument. | 461 // Continuation or FunctionDefinition if the primitive is an argument. |
| 460 if (parent is LetPrim && _isDeadVal(parent)) { | 462 if (parent is LetPrim && _isDeadVal(parent)) { |
| 461 worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, parent)); | 463 worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, parent)); |
| 462 } | 464 } |
| 463 } else if (reference.definition is Continuation) { | 465 } else if (reference.definition is Continuation) { |
| 464 Continuation cont = reference.definition; | 466 Continuation cont = reference.definition; |
| 465 Node parent = cont.parent; | 467 Node parent = cont.parent; |
| 466 // The parent might be the deleted sentinel, or it might be a | 468 // The parent might be the deleted sentinel, or it might be a |
| 467 // RunnableBody if the continuation is the return continuation. | 469 // Body if the continuation is the return continuation. |
| 468 if (parent is LetCont) { | 470 if (parent is LetCont) { |
| 469 if (cont.isRecursive && cont.hasAtMostOneUse) { | 471 if (cont.isRecursive && cont.hasAtMostOneUse) { |
| 470 // Convert recursive to nonrecursive continuations. If the | 472 // Convert recursive to nonrecursive continuations. If the |
| 471 // continuation is still in use, it is either dead and will be | 473 // continuation is still in use, it is either dead and will be |
| 472 // removed, or it is called nonrecursively outside its body. | 474 // removed, or it is called nonrecursively outside its body. |
| 473 cont.isRecursive = false; | 475 cont.isRecursive = false; |
| 474 } | 476 } |
| 475 if (_isDeadCont(cont)) { | 477 if (_isDeadCont(cont)) { |
| 476 worklist.add(new _ReductionTask(_ReductionKind.DEAD_CONT, cont)); | 478 worklist.add(new _ReductionTask(_ReductionKind.DEAD_CONT, cont)); |
| 477 } else if (_isBetaContLin(cont)) { | 479 } else if (_isBetaContLin(cont)) { |
| 478 worklist.add(new _ReductionTask(_ReductionKind.BETA_CONT_LIN, cont)); | 480 worklist.add(new _ReductionTask(_ReductionKind.BETA_CONT_LIN, cont)); |
| 479 } | 481 } |
| 480 } | 482 } |
| 481 } | 483 } |
| 482 } | 484 } |
| 483 } | 485 } |
| 484 | 486 |
| 485 /// Traverses the CPS term and sets node.parent for each visited node. | 487 /// Traverses the CPS term and sets node.parent for each visited node. |
| 486 class ParentVisitor extends RecursiveVisitor { | 488 class ParentVisitor extends RecursiveVisitor { |
| 487 processFunctionDefinition(FunctionDefinition node) { | 489 processFunctionDefinition(FunctionDefinition node) { |
| 488 node.body.parent = node; | 490 node.body.parent = node; |
| 489 if (node.thisParameter != null) node.thisParameter.parent = node; | 491 if (node.thisParameter != null) node.thisParameter.parent = node; |
| 490 int index = 0; | 492 int index = 0; |
| 491 node.parameters.forEach((Definition parameter) { | 493 node.parameters.forEach((Definition parameter) { |
| 492 parameter.parent = node; | 494 parameter.parent = node; |
| 493 if (parameter is Parameter) parameter.parentIndex = index++; | 495 if (parameter is Parameter) parameter.parentIndex = index++; |
| 494 }); | 496 }); |
| 495 } | 497 } |
| 496 | 498 |
| 497 processRunnableBody(RunnableBody node) { | 499 processBody(Body node) { |
| 498 node.returnContinuation.parent = node; | 500 node.returnContinuation.parent = node; |
| 499 node.body.parent = node; | 501 node.body.parent = node; |
| 500 } | 502 } |
| 501 | 503 |
| 502 processConstructorDefinition(ConstructorDefinition node) { | 504 processConstructorDefinition(ConstructorDefinition node) { |
| 503 node.body.parent = node; | 505 node.body.parent = node; |
| 504 int index = 0; | 506 int index = 0; |
| 505 node.parameters.forEach((Definition parameter) { | 507 node.parameters.forEach((Definition parameter) { |
| 506 parameter.parent = node; | 508 parameter.parent = node; |
| 507 if (parameter is Parameter) parameter.parentIndex = index++; | 509 if (parameter is Parameter) parameter.parentIndex = index++; |
| 508 }); | 510 }); |
| 509 node.initializers.forEach((Initializer i) => i.parent = node); | 511 node.initializers.forEach((Initializer i) => i.parent = node); |
| 510 } | 512 } |
| 511 | 513 |
| 512 // Expressions. | 514 // Expressions. |
| 513 | 515 |
| 514 processFieldInitializer(FieldInitializer node) { | 516 processFieldInitializer(FieldInitializer node) { |
| 515 node.body.parent = node; | 517 node.body.parent = node; |
| 516 } | 518 } |
| 517 | 519 |
| 518 processSuperInitializer(SuperInitializer node) { | 520 processSuperInitializer(SuperInitializer node) { |
| 519 node.arguments.forEach((RunnableBody argument) => argument.parent = node); | 521 node.arguments.forEach((Body argument) => argument.parent = node); |
| 520 } | 522 } |
| 521 | 523 |
| 522 processLetPrim(LetPrim node) { | 524 processLetPrim(LetPrim node) { |
| 523 node.primitive.parent = node; | 525 node.primitive.parent = node; |
| 524 node.body.parent = node; | 526 node.body.parent = node; |
| 525 } | 527 } |
| 526 | 528 |
| 527 processLetCont(LetCont node) { | 529 processLetCont(LetCont node) { |
| 528 int index = 0; | 530 int index = 0; |
| 529 node.continuations.forEach((Continuation continuation) { | 531 node.continuations.forEach((Continuation continuation) { |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 } | 716 } |
| 715 | 717 |
| 716 String toString() => "$kind: $node"; | 718 String toString() => "$kind: $node"; |
| 717 } | 719 } |
| 718 | 720 |
| 719 /// A dummy class used solely to mark nodes as deleted once they are removed | 721 /// A dummy class used solely to mark nodes as deleted once they are removed |
| 720 /// from a term. | 722 /// from a term. |
| 721 class _DeletedNode extends Node { | 723 class _DeletedNode extends Node { |
| 722 accept(_) => null; | 724 accept(_) => null; |
| 723 } | 725 } |
| OLD | NEW |