| 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 dart2js.cps_ir.redundant_join_elimination; | 5 library dart2js.cps_ir.redundant_join_elimination; |
| 6 | 6 |
| 7 import 'cps_ir_nodes.dart'; | 7 import 'cps_ir_nodes.dart'; |
| 8 import 'optimizers.dart'; | 8 import 'optimizers.dart'; |
| 9 | 9 |
| 10 /// Eliminates redundant join points. | 10 /// Eliminates redundant join points. |
| 11 /// | 11 /// |
| 12 /// A redundant join point is a continuation that immediately branches | 12 /// A redundant join point is a continuation that immediately branches |
| 13 /// based on one of its parameters, and that parameter is a constant value | 13 /// based on one of its parameters, and that parameter is a constant value |
| 14 /// at every invocation. Each invocation is redirected to jump directly | 14 /// at every invocation. Each invocation is redirected to jump directly |
| 15 /// to the branch target. | 15 /// to the branch target. |
| 16 /// | 16 /// |
| 17 /// Internally in this pass, parameters are treated as names with lexical | 17 /// Internally in this pass, parameters are treated as names with lexical |
| 18 /// scoping, and a given parameter "name" may be declared by more than | 18 /// scoping, and a given parameter "name" may be declared by more than |
| 19 /// one continuation. The reference chains for parameters are therefore | 19 /// one continuation. The reference chains for parameters are therefore |
| 20 /// meaningless during this pass, until repaired by [AlphaRenamer] at | 20 /// meaningless during this pass, until repaired by [AlphaRenamer] at |
| 21 /// the end. | 21 /// the end. |
| 22 class RedundantJoinEliminator extends RecursiveVisitor implements Pass { | 22 class RedundantJoinEliminator extends TrampolineRecursiveVisitor implements Pass
{ |
| 23 String get passName => 'Redundant join elimination'; | 23 String get passName => 'Redundant join elimination'; |
| 24 | 24 |
| 25 final Set<Branch> workSet = new Set<Branch>(); | 25 final Set<Branch> workSet = new Set<Branch>(); |
| 26 | 26 |
| 27 void rewrite(FunctionDefinition node) { | 27 void rewrite(FunctionDefinition node) { |
| 28 visit(node); | 28 visit(node); |
| 29 | 29 |
| 30 while (workSet.isNotEmpty) { | 30 while (workSet.isNotEmpty) { |
| 31 Branch branch = workSet.first; | 31 Branch branch = workSet.first; |
| 32 workSet.remove(branch); | 32 workSet.remove(branch); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 // continuations. [AlphaRenamer] will clean up at the end of this pass. | 132 // continuations. [AlphaRenamer] will clean up at the end of this pass. |
| 133 LetCont outerLetCont = branchCont.parent; | 133 LetCont outerLetCont = branchCont.parent; |
| 134 while (branchCont.body is LetCont) { | 134 while (branchCont.body is LetCont) { |
| 135 LetCont innerLetCont = branchCont.body; | 135 LetCont innerLetCont = branchCont.body; |
| 136 for (Continuation innerCont in innerLetCont.continuations) { | 136 for (Continuation innerCont in innerLetCont.continuations) { |
| 137 innerCont.parameters.addAll(branchCont.parameters); | 137 innerCont.parameters.addAll(branchCont.parameters); |
| 138 for (Reference ref = innerCont.firstRef; ref != null; ref = ref.next) { | 138 for (Reference ref = innerCont.firstRef; ref != null; ref = ref.next) { |
| 139 Expression use = ref.parent; | 139 Expression use = ref.parent; |
| 140 if (use is InvokeContinuation) { | 140 if (use is InvokeContinuation) { |
| 141 for (Parameter param in branchCont.parameters) { | 141 for (Parameter param in branchCont.parameters) { |
| 142 use.arguments.add(new Reference<Primitive>(param)); | 142 use.arguments.add(new Reference<Primitive>(param)..parent = use); |
| 143 } | 143 } |
| 144 } else { | 144 } else { |
| 145 // The branch will be eliminated, so don't worry about updating it. | 145 // The branch will be eliminated, so don't worry about updating it. |
| 146 assert(use == branch); | 146 assert(use == branch); |
| 147 } | 147 } |
| 148 } | 148 } |
| 149 } | 149 } |
| 150 innerLetCont.remove(); | 150 innerLetCont.remove(); |
| 151 innerLetCont.insertAbove(outerLetCont); | 151 innerLetCont.insertAbove(outerLetCont); |
| 152 } | 152 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 /// => | 208 /// => |
| 209 /// LetCont (k1 x = (return x)) in | 209 /// LetCont (k1 x = (return x)) in |
| 210 /// LetCont (k2 x' = (InvokeContinuation k3 x')) in ... | 210 /// LetCont (k2 x' = (InvokeContinuation k3 x')) in ... |
| 211 /// | 211 /// |
| 212 /// After lifting LetConts in the main pass above, parameter objects can have | 212 /// After lifting LetConts in the main pass above, parameter objects can have |
| 213 /// multiple bindings. Each reference implicitly refers to the binding that | 213 /// multiple bindings. Each reference implicitly refers to the binding that |
| 214 /// is currently in scope. | 214 /// is currently in scope. |
| 215 /// | 215 /// |
| 216 /// This returns the IR to its normal form after redundant joins have been | 216 /// This returns the IR to its normal form after redundant joins have been |
| 217 /// eliminated. | 217 /// eliminated. |
| 218 class AlphaRenamer extends RecursiveVisitor { | 218 class AlphaRenamer extends TrampolineRecursiveVisitor { |
| 219 Map<Parameter, Parameter> renaming = <Parameter, Parameter>{}; | 219 Map<Parameter, Parameter> renaming = <Parameter, Parameter>{}; |
| 220 | 220 |
| 221 processContinuation(Continuation cont) { | 221 processContinuation(Continuation cont) { |
| 222 if (cont.isReturnContinuation) return; | 222 if (cont.isReturnContinuation) return; |
| 223 | 223 |
| 224 List<Parameter> shadowedKeys = <Parameter>[]; | 224 List<Parameter> shadowedKeys = <Parameter>[]; |
| 225 List<Parameter> shadowedValues = <Parameter>[]; | 225 List<Parameter> shadowedValues = <Parameter>[]; |
| 226 | 226 |
| 227 // Create new parameters and update the environment. | 227 // Create new parameters and update the environment. |
| 228 for (int i = 0; i < cont.parameters.length; ++i) { | 228 for (int i = 0; i < cont.parameters.length; ++i) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 251 }); | 251 }); |
| 252 } | 252 } |
| 253 | 253 |
| 254 processReference(Reference ref) { | 254 processReference(Reference ref) { |
| 255 Parameter target = renaming[ref.definition]; | 255 Parameter target = renaming[ref.definition]; |
| 256 if (target != null) { | 256 if (target != null) { |
| 257 ref.changeTo(target); | 257 ref.changeTo(target); |
| 258 } | 258 } |
| 259 } | 259 } |
| 260 } | 260 } |
| OLD | NEW |