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 |