| 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.mutable_ssa; | 5 library dart2js.cps_ir.mutable_ssa; |
| 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 /// Determines which mutable variables should be rewritten to phi assignments | 10 /// Determines which mutable variables should be rewritten to phi assignments |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 ++currentDepth; | 32 ++currentDepth; |
| 33 pushAction(() => --currentDepth); | 33 pushAction(() => --currentDepth); |
| 34 return node.body; | 34 return node.body; |
| 35 } | 35 } |
| 36 | 36 |
| 37 void processLetMutable(LetMutable node) { | 37 void processLetMutable(LetMutable node) { |
| 38 variableDepth[node.variable] = currentDepth; | 38 variableDepth[node.variable] = currentDepth; |
| 39 } | 39 } |
| 40 | 40 |
| 41 void processSetMutable(SetMutable node) { | 41 void processSetMutable(SetMutable node) { |
| 42 MutableVariable variable = node.variable.definition; | 42 MutableVariable variable = node.variable; |
| 43 if (currentDepth > variableDepth[variable]) { | 43 if (currentDepth > variableDepth[variable]) { |
| 44 hasAssignmentInTry.add(variable); | 44 hasAssignmentInTry.add(variable); |
| 45 } | 45 } |
| 46 } | 46 } |
| 47 | 47 |
| 48 /// True if there are no mutable variables or they are all assigned inside | 48 /// True if there are no mutable variables or they are all assigned inside |
| 49 /// a try block. In this case, there is nothing to do and the pass should | 49 /// a try block. In this case, there is nothing to do and the pass should |
| 50 /// be skipped. | 50 /// be skipped. |
| 51 bool get allMutablesAreAssignedInTryBlocks { | 51 bool get allMutablesAreAssignedInTryBlocks { |
| 52 return hasAssignmentInTry.length == variableDepth.length; | 52 return hasAssignmentInTry.length == variableDepth.length; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 Map<MutableVariable, Primitive> environment) { | 135 Map<MutableVariable, Primitive> environment) { |
| 136 Expression next = node.next; | 136 Expression next = node.next; |
| 137 for (; node is! TailExpression; node = next, next = node.next) { | 137 for (; node is! TailExpression; node = next, next = node.next) { |
| 138 if (node is LetMutable && shouldRewrite(node.variable)) { | 138 if (node is LetMutable && shouldRewrite(node.variable)) { |
| 139 // Put the new mutable variable on the stack while processing the body, | 139 // Put the new mutable variable on the stack while processing the body, |
| 140 // and pop it off again when done with the body. | 140 // and pop it off again when done with the body. |
| 141 mutableVariables.add(node.variable); | 141 mutableVariables.add(node.variable); |
| 142 stack.add(new VariableItem()); | 142 stack.add(new VariableItem()); |
| 143 | 143 |
| 144 // Put the initial value into the environment. | 144 // Put the initial value into the environment. |
| 145 Primitive value = node.value.definition; | 145 Primitive value = node.value; |
| 146 environment[node.variable] = value; | 146 environment[node.variable] = value; |
| 147 | 147 |
| 148 // Preserve variable names. | 148 // Preserve variable names. |
| 149 mergeHints(node.variable, value); | 149 mergeHints(node.variable, value); |
| 150 | 150 |
| 151 // Remove the mutable variable binding. | 151 // Remove the mutable variable binding. |
| 152 node.value.unlink(); | 152 node.valueRef.unlink(); |
| 153 node.remove(); | 153 node.remove(); |
| 154 } else if (node is LetPrim && node.primitive is SetMutable) { | 154 } else if (node is LetPrim && node.primitive is SetMutable) { |
| 155 SetMutable setter = node.primitive; | 155 SetMutable setter = node.primitive; |
| 156 MutableVariable variable = setter.variable.definition; | 156 MutableVariable variable = setter.variable; |
| 157 if (shouldRewrite(variable)) { | 157 if (shouldRewrite(variable)) { |
| 158 // As above, update the environment, preserve variables and remove | 158 // As above, update the environment, preserve variables and remove |
| 159 // the mutable variable assignment. | 159 // the mutable variable assignment. |
| 160 environment[variable] = setter.value.definition; | 160 environment[variable] = setter.value; |
| 161 mergeHints(variable, setter.value.definition); | 161 mergeHints(variable, setter.value); |
| 162 setter.value.unlink(); | 162 setter.valueRef.unlink(); |
| 163 node.remove(); | 163 node.remove(); |
| 164 } | 164 } |
| 165 } else if (node is LetPrim && node.primitive is GetMutable) { | 165 } else if (node is LetPrim && node.primitive is GetMutable) { |
| 166 GetMutable getter = node.primitive; | 166 GetMutable getter = node.primitive; |
| 167 MutableVariable variable = getter.variable.definition; | 167 MutableVariable variable = getter.variable; |
| 168 if (shouldRewrite(variable)) { | 168 if (shouldRewrite(variable)) { |
| 169 // Replace with the reaching definition from the environment. | 169 // Replace with the reaching definition from the environment. |
| 170 Primitive value = environment[variable]; | 170 Primitive value = environment[variable]; |
| 171 getter.replaceUsesWith(value); | 171 getter.replaceUsesWith(value); |
| 172 mergeHints(variable, value); | 172 mergeHints(variable, value); |
| 173 node.remove(); | 173 node.remove(); |
| 174 } | 174 } |
| 175 } else if (node is LetCont) { | 175 } else if (node is LetCont) { |
| 176 // Create phi parameters for each join continuation bound here, and put | 176 // Create phi parameters for each join continuation bound here, and put |
| 177 // them on the stack for later processing. | 177 // them on the stack for later processing. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 199 // The current environment bindings cannot change inside the try block | 199 // The current environment bindings cannot change inside the try block |
| 200 // because we exclude all variables assigned inside a try block. | 200 // because we exclude all variables assigned inside a try block. |
| 201 // The environment might be extended with more bindings before we | 201 // The environment might be extended with more bindings before we |
| 202 // analyze the catch block, but that's ok. | 202 // analyze the catch block, but that's ok. |
| 203 stack.add(new ContinuationItem(node.handler, environment)); | 203 stack.add(new ContinuationItem(node.handler, environment)); |
| 204 } | 204 } |
| 205 } | 205 } |
| 206 | 206 |
| 207 // Analyze the terminal node. | 207 // Analyze the terminal node. |
| 208 if (node is InvokeContinuation) { | 208 if (node is InvokeContinuation) { |
| 209 Continuation cont = node.continuation.definition; | 209 Continuation cont = node.continuation; |
| 210 if (cont.isReturnContinuation) return; | 210 if (cont.isReturnContinuation) return; |
| 211 // This is a call to a join continuation. Add arguments for the phi | 211 // This is a call to a join continuation. Add arguments for the phi |
| 212 // parameters that were added to this continuation. | 212 // parameters that were added to this continuation. |
| 213 int phiCount = continuationPhiCount[cont]; | 213 int phiCount = continuationPhiCount[cont]; |
| 214 for (int i = 0; i < phiCount; ++i) { | 214 for (int i = 0; i < phiCount; ++i) { |
| 215 Primitive value = environment[mutableVariables[i]]; | 215 Primitive value = environment[mutableVariables[i]]; |
| 216 Reference<Primitive> arg = new Reference<Primitive>(value); | 216 Reference<Primitive> arg = new Reference<Primitive>(value); |
| 217 node.arguments.add(arg); | 217 node.argumentRefs.add(arg); |
| 218 arg.parent = node; | 218 arg.parent = node; |
| 219 } | 219 } |
| 220 } else if (node is Branch) { | 220 } else if (node is Branch) { |
| 221 // Enqueue both branches with the current environment. | 221 // Enqueue both branches with the current environment. |
| 222 // Clone the environments once so the processing of one branch does not | 222 // Clone the environments once so the processing of one branch does not |
| 223 // mutate the environment needed to process the other branch. | 223 // mutate the environment needed to process the other branch. |
| 224 stack.add(new ContinuationItem( | 224 stack.add(new ContinuationItem( |
| 225 node.trueContinuation.definition, | 225 node.trueContinuation, |
| 226 new Map<MutableVariable, Primitive>.from(environment))); | 226 new Map<MutableVariable, Primitive>.from(environment))); |
| 227 stack.add(new ContinuationItem( | 227 stack.add(new ContinuationItem( |
| 228 node.falseContinuation.definition, | 228 node.falseContinuation, |
| 229 environment)); | 229 environment)); |
| 230 } else { | 230 } else { |
| 231 assert(node is Throw || node is Unreachable); | 231 assert(node is Throw || node is Unreachable); |
| 232 } | 232 } |
| 233 } | 233 } |
| 234 } | 234 } |
| 235 | 235 |
| 236 abstract class StackItem {} | 236 abstract class StackItem {} |
| 237 | 237 |
| 238 /// Represents a mutable variable that is in scope. | 238 /// Represents a mutable variable that is in scope. |
| 239 /// | 239 /// |
| 240 /// The topmost mutable variable falls out of scope when this item is | 240 /// The topmost mutable variable falls out of scope when this item is |
| 241 /// taken off the stack. | 241 /// taken off the stack. |
| 242 class VariableItem extends StackItem {} | 242 class VariableItem extends StackItem {} |
| 243 | 243 |
| 244 /// Represents a yet unprocessed continuation together with the | 244 /// Represents a yet unprocessed continuation together with the |
| 245 /// environment in which to process it. | 245 /// environment in which to process it. |
| 246 class ContinuationItem extends StackItem { | 246 class ContinuationItem extends StackItem { |
| 247 final Continuation continuation; | 247 final Continuation continuation; |
| 248 final Map<MutableVariable, Primitive> environment; | 248 final Map<MutableVariable, Primitive> environment; |
| 249 | 249 |
| 250 ContinuationItem(this.continuation, this.environment); | 250 ContinuationItem(this.continuation, this.environment); |
| 251 } | 251 } |
| OLD | NEW |