Chromium Code Reviews| 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. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 if (!branchCont.hasMultipleUses) return; | 73 if (!branchCont.hasMultipleUses) return; |
| 74 | 74 |
| 75 // It might be beneficial to rewrite calls to recursive continuations, | 75 // It might be beneficial to rewrite calls to recursive continuations, |
| 76 // but we currently do not support this. | 76 // but we currently do not support this. |
| 77 if (branchCont.isRecursive) return; | 77 if (branchCont.isRecursive) return; |
| 78 | 78 |
| 79 // Check that the branching condition is a parameter on the | 79 // Check that the branching condition is a parameter on the |
| 80 // enclosing continuation. | 80 // enclosing continuation. |
| 81 // Note: Do not use the parent pointer for this check, because parameters | 81 // Note: Do not use the parent pointer for this check, because parameters |
| 82 // are temporarily shared between different continuations during this pass. | 82 // are temporarily shared between different continuations during this pass. |
| 83 Primitive condition = branch.condition.definition; | 83 Primitive condition = branch.condition; |
| 84 int parameterIndex = branchCont.parameters.indexOf(condition); | 84 int parameterIndex = branchCont.parameters.indexOf(condition); |
| 85 if (parameterIndex == -1) return; | 85 if (parameterIndex == -1) return; |
| 86 | 86 |
| 87 // Check that all callers hit a fixed branch, and count the number | 87 // Check that all callers hit a fixed branch, and count the number |
| 88 // of times each branch is hit. | 88 // of times each branch is hit. |
| 89 // We know all callers are InvokeContinuations because they are the only | 89 // We know all callers are InvokeContinuations because they are the only |
| 90 // valid uses of a multi-use continuation. | 90 // valid uses of a multi-use continuation. |
| 91 int trueHits = 0, falseHits = 0; | 91 int trueHits = 0, falseHits = 0; |
| 92 InvokeContinuation trueCall, falseCall; | 92 InvokeContinuation trueCall, falseCall; |
| 93 for (Reference ref = branchCont.firstRef; ref != null; ref = ref.next) { | 93 for (Reference ref = branchCont.firstRef; ref != null; ref = ref.next) { |
| 94 InvokeContinuation invoke = ref.parent; | 94 InvokeContinuation invoke = ref.parent; |
| 95 Primitive argument = invoke.arguments[parameterIndex].definition; | 95 Primitive argument = invoke.argument(parameterIndex); |
| 96 if (argument is! Constant) return; // Branching condition is unknown. | 96 if (argument is! Constant) return; // Branching condition is unknown. |
| 97 Constant constant = argument; | 97 Constant constant = argument; |
| 98 if (isTruthyConstant(constant.value, strict: branch.isStrictCheck)) { | 98 if (isTruthyConstant(constant.value, strict: branch.isStrictCheck)) { |
| 99 ++trueHits; | 99 ++trueHits; |
| 100 trueCall = invoke; | 100 trueCall = invoke; |
| 101 } else { | 101 } else { |
| 102 ++falseHits; | 102 ++falseHits; |
| 103 falseCall = invoke; | 103 falseCall = invoke; |
| 104 } | 104 } |
| 105 } | 105 } |
| (...skipping 26 matching lines...) Expand all 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)..parent = use); | 142 use.argumentRefs.add(new Reference<Primitive>(param)..parent = use ); |
|
Siggi Cherem (dart-lang)
2016/02/29 18:00:00
80 col
asgerf
2016/03/01 12:06:59
Done.
| |
| 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 } |
| 153 | 153 |
| 154 assert(branchCont.body == branch); | 154 assert(branchCont.body == branch); |
| 155 | 155 |
| 156 Continuation trueCont = branch.trueContinuation.definition; | 156 Continuation trueCont = branch.trueContinuation; |
| 157 Continuation falseCont = branch.falseContinuation.definition; | 157 Continuation falseCont = branch.falseContinuation; |
| 158 | 158 |
| 159 assert(branchCont != trueCont); | 159 assert(branchCont != trueCont); |
| 160 assert(branchCont != falseCont); | 160 assert(branchCont != falseCont); |
| 161 | 161 |
| 162 // Rewrite every invocation of branchCont to call either the true or false | 162 // Rewrite every invocation of branchCont to call either the true or false |
| 163 // branch directly. Since these were lifted out above branchCont, they are | 163 // branch directly. Since these were lifted out above branchCont, they are |
| 164 // now in scope. | 164 // now in scope. |
| 165 // Since trueCont and falseCont were branch targets, they originally | 165 // Since trueCont and falseCont were branch targets, they originally |
| 166 // had no parameters, and so after the lifting, their parameters are | 166 // had no parameters, and so after the lifting, their parameters are |
| 167 // exactly the same as those accepted by branchCont. | 167 // exactly the same as those accepted by branchCont. |
| 168 while (branchCont.firstRef != null) { | 168 while (branchCont.firstRef != null) { |
| 169 Reference reference = branchCont.firstRef; | 169 Reference reference = branchCont.firstRef; |
| 170 InvokeContinuation invoke = branchCont.firstRef.parent; | 170 InvokeContinuation invoke = branchCont.firstRef.parent; |
| 171 Constant condition = invoke.arguments[parameterIndex].definition; | 171 Constant condition = invoke.argument(parameterIndex); |
| 172 if (isTruthyConstant(condition.value, strict: branch.isStrictCheck)) { | 172 if (isTruthyConstant(condition.value, strict: branch.isStrictCheck)) { |
| 173 invoke.continuation.changeTo(trueCont); | 173 invoke.continuationRef.changeTo(trueCont); |
| 174 } else { | 174 } else { |
| 175 invoke.continuation.changeTo(falseCont); | 175 invoke.continuationRef.changeTo(falseCont); |
| 176 } | 176 } |
| 177 assert(branchCont.firstRef != reference); | 177 assert(branchCont.firstRef != reference); |
| 178 } | 178 } |
| 179 | 179 |
| 180 // Remove the now-unused branchCont continuation. | 180 // Remove the now-unused branchCont continuation. |
| 181 assert(branchCont.hasNoUses); | 181 assert(branchCont.hasNoUses); |
| 182 branch.trueContinuation.unlink(); | 182 branch.trueContinuationRef.unlink(); |
| 183 branch.falseContinuation.unlink(); | 183 branch.falseContinuationRef.unlink(); |
| 184 outerLetCont.continuations.remove(branchCont); | 184 outerLetCont.continuations.remove(branchCont); |
| 185 if (outerLetCont.continuations.isEmpty) { | 185 if (outerLetCont.continuations.isEmpty) { |
| 186 outerLetCont.remove(); | 186 outerLetCont.remove(); |
| 187 } | 187 } |
| 188 | 188 |
| 189 // We may have created new redundant join points in the two branches. | 189 // We may have created new redundant join points in the two branches. |
| 190 enqueueContinuation(trueCont); | 190 enqueueContinuation(trueCont); |
| 191 enqueueContinuation(falseCont); | 191 enqueueContinuation(falseCont); |
| 192 } | 192 } |
| 193 | 193 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after 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 |