OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import '../closure.dart'; | 5 import '../closure.dart'; |
6 import '../common.dart'; | 6 import '../common.dart'; |
7 import '../elements/elements.dart'; | 7 import '../elements/elements.dart'; |
8 import '../elements/entities.dart'; | 8 import '../elements/entities.dart'; |
9 import '../elements/types.dart'; | 9 import '../elements/types.dart'; |
10 import '../io/source_information.dart'; | 10 import '../io/source_information.dart'; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 } | 129 } |
130 | 130 |
131 HInstruction createBox() { | 131 HInstruction createBox() { |
132 HInstruction box = new HCreateBox(commonMasks.nonNullType); | 132 HInstruction box = new HCreateBox(commonMasks.nonNullType); |
133 builder.add(box); | 133 builder.add(box); |
134 return box; | 134 return box; |
135 } | 135 } |
136 | 136 |
137 /// If the scope (function or loop) [node] has captured variables then this | 137 /// If the scope (function or loop) [node] has captured variables then this |
138 /// method creates a box and sets up the redirections. | 138 /// method creates a box and sets up the redirections. |
139 void enterScope(ClosureAnalysisInfo closureInfo, | 139 void enterScope(ClosureBase closureInfo, |
140 {bool forGenerativeConstructorBody: false}) { | 140 {bool forGenerativeConstructorBody: false}) { |
141 // See if any variable in the top-scope of the function is captured. If yes | 141 // See if any variable in the top-scope of the function is captured. If yes |
142 // we need to create a box-object. | 142 // we need to create a box-object. |
143 if (!closureInfo.requiresContextBox) return; | 143 if (!closureInfo.requiresContextBox) return; |
144 HInstruction box; | 144 HInstruction box; |
145 // The scope has captured variables. | 145 // The scope has captured variables. |
146 if (forGenerativeConstructorBody) { | 146 if (forGenerativeConstructorBody) { |
147 // The box is passed as a parameter to a generative | 147 // The box is passed as a parameter to a generative |
148 // constructor body. | 148 // constructor body. |
149 box = builder.addParameter(closureInfo.context, commonMasks.nonNullType); | 149 box = builder.addParameter(closureInfo.context, commonMasks.nonNullType); |
150 } else { | 150 } else { |
151 box = createBox(); | 151 box = createBox(); |
152 } | 152 } |
153 // Add the box to the known locals. | 153 // Add the box to the known locals. |
154 directLocals[closureInfo.context] = box; | 154 directLocals[closureInfo.context] = box; |
155 // Make sure that accesses to the boxed locals go into the box. We also | 155 // Make sure that accesses to the boxed locals go into the box. We also |
156 // need to make sure that parameters are copied into the box if necessary. | 156 // need to make sure that parameters are copied into the box if necessary. |
157 closureInfo.forEachCapturedVariable((_from, _to) { | 157 closureInfo.forEachBoxedVariable((_from, _to) { |
158 LocalVariableElement from = _from; | 158 LocalVariableElement from = _from; |
159 BoxFieldElement to = _to; | 159 BoxFieldElement to = _to; |
160 // The [from] can only be a parameter for function-scopes and not | 160 // The [from] can only be a parameter for function-scopes and not |
161 // loop scopes. | 161 // loop scopes. |
162 if (from.isRegularParameter && !forGenerativeConstructorBody) { | 162 if (from.isRegularParameter && !forGenerativeConstructorBody) { |
163 // Now that the redirection is set up, the update to the local will | 163 // Now that the redirection is set up, the update to the local will |
164 // write the parameter value into the box. | 164 // write the parameter value into the box. |
165 // Store the captured parameter in the box. Get the current value | 165 // Store the captured parameter in the box. Get the current value |
166 // before we put the redirection in place. | 166 // before we put the redirection in place. |
167 // We don't need to update the local for a generative | 167 // We don't need to update the local for a generative |
168 // constructor body, because it receives a box that already | 168 // constructor body, because it receives a box that already |
169 // contains the updates as the last parameter. | 169 // contains the updates as the last parameter. |
170 HInstruction instruction = readLocal(from); | 170 HInstruction instruction = readLocal(from); |
171 redirectElement(from, to); | 171 redirectElement(from, to); |
172 updateLocal(from, instruction); | 172 updateLocal(from, instruction); |
173 } else { | 173 } else { |
174 redirectElement(from, to); | 174 redirectElement(from, to); |
175 } | 175 } |
176 }); | 176 }); |
177 } | 177 } |
178 | 178 |
179 /// Replaces the current box with a new box and copies over the given list | 179 /// Replaces the current box with a new box and copies over the given list |
180 /// of elements from the old box into the new box. | 180 /// of elements from the old box into the new box. |
181 void updateCaptureBox(Local boxElement, List<Local> toBeCopiedElements) { | 181 void updateCaptureBox(ClosureBase loopInfo) { |
| 182 Local boxElement = loopInfo.context; |
182 // Create a new box and copy over the values from the old box into the | 183 // Create a new box and copy over the values from the old box into the |
183 // new one. | 184 // new one. |
184 HInstruction oldBox = readLocal(boxElement); | 185 HInstruction oldBox = readLocal(boxElement); |
185 HInstruction newBox = createBox(); | 186 HInstruction newBox = createBox(); |
186 for (Local boxedVariable in toBeCopiedElements) { | 187 loopInfo.forEachBoxedVariable((Local boxedVariable, _) { |
187 // [readLocal] uses the [boxElement] to find its box. By replacing it | 188 // [readLocal] uses the [boxElement] to find its box. By replacing it |
188 // behind its back we can still get to the old values. | 189 // behind its back we can still get to the old values. |
189 updateLocal(boxElement, oldBox); | 190 updateLocal(boxElement, oldBox); |
190 HInstruction oldValue = readLocal(boxedVariable); | 191 HInstruction oldValue = readLocal(boxedVariable); |
191 updateLocal(boxElement, newBox); | 192 updateLocal(boxElement, newBox); |
192 updateLocal(boxedVariable, oldValue); | 193 updateLocal(boxedVariable, oldValue); |
193 } | 194 }); |
194 updateLocal(boxElement, newBox); | 195 updateLocal(boxElement, newBox); |
195 } | 196 } |
196 | 197 |
197 /// Documentation wanted -- johnniwinther | 198 /// Documentation wanted -- johnniwinther |
198 /// | 199 /// |
199 /// Invariant: [function] must be an implementation element. | 200 /// Invariant: [function] must be an implementation element. |
200 void startFunction(MemberEntity element, ScopeInfo scopeInfo, | 201 void startFunction(MemberEntity element, ScopeInfo scopeInfo, |
201 ClosureAnalysisInfo scopeData, Map<Local, TypeMask> parameters, | 202 ClosureBase scopeData, Map<Local, TypeMask> parameters, |
202 {bool isGenerativeConstructorBody}) { | 203 {bool isGenerativeConstructorBody}) { |
203 assert(!(element is MemberElement && !element.isImplementation), | 204 assert(!(element is MemberElement && !element.isImplementation), |
204 failedAt(element)); | 205 failedAt(element)); |
205 this.scopeInfo = scopeInfo; | 206 this.scopeInfo = scopeInfo; |
206 | 207 |
207 parameters.forEach((Local local, TypeMask typeMask) { | 208 parameters.forEach((Local local, TypeMask typeMask) { |
208 if (isGenerativeConstructorBody) { | 209 if (isGenerativeConstructorBody) { |
209 if (scopeData.isCaptured(local)) { | 210 if (scopeData.isBoxed(local)) { |
210 // The parameter will be a field in the box passed as the | 211 // The parameter will be a field in the box passed as the |
211 // last parameter. So no need to have it. | 212 // last parameter. So no need to have it. |
212 return; | 213 return; |
213 } | 214 } |
214 } | 215 } |
215 HInstruction parameter = builder.addParameter(local, typeMask); | 216 HInstruction parameter = builder.addParameter(local, typeMask); |
216 builder.parameters[local] = parameter; | 217 builder.parameters[local] = parameter; |
217 directLocals[local] = parameter; | 218 directLocals[local] = parameter; |
218 }); | 219 }); |
219 | 220 |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 /// We solve this by emitting the following code (only for [ast.For] loops): | 470 /// We solve this by emitting the following code (only for [ast.For] loops): |
470 /// <Create box> <== move the first box creation outside the loop. | 471 /// <Create box> <== move the first box creation outside the loop. |
471 /// <initializer>; | 472 /// <initializer>; |
472 /// loop-entry: | 473 /// loop-entry: |
473 /// if (!<condition>) goto loop-exit; | 474 /// if (!<condition>) goto loop-exit; |
474 /// <body> | 475 /// <body> |
475 /// <update box> // create a new box and copy the captured loop-variables. | 476 /// <update box> // create a new box and copy the captured loop-variables. |
476 /// <updates> | 477 /// <updates> |
477 /// goto loop-entry; | 478 /// goto loop-entry; |
478 /// loop-exit: | 479 /// loop-exit: |
479 void startLoop(LoopClosureRepresentationInfo loopInfo) { | 480 void startLoop(ClosureBase loopInfo) { |
480 if (loopInfo.hasBoxedVariables) { | 481 if (loopInfo.hasBoxedVariables) { |
481 // If there are boxed loop variables then we set up the box and | 482 // If there are boxed loop variables then we set up the box and |
482 // redirections already now. This way the initializer can write its | 483 // redirections already now. This way the initializer can write its |
483 // values into the box. | 484 // values into the box. |
484 // For other loops the box will be created when entering the body. | 485 // For other loops the box will be created when entering the body. |
485 enterScope(loopInfo); | 486 enterScope(loopInfo); |
486 } | 487 } |
487 } | 488 } |
488 | 489 |
489 /// Create phis at the loop entry for local variables (ready for the values | 490 /// Create phis at the loop entry for local variables (ready for the values |
(...skipping 12 matching lines...) Expand all Loading... |
502 new HPhi.singleInput(local, instruction, commonMasks.dynamicType); | 503 new HPhi.singleInput(local, instruction, commonMasks.dynamicType); |
503 loopEntry.addPhi(phi); | 504 loopEntry.addPhi(phi); |
504 directLocals[local] = phi; | 505 directLocals[local] = phi; |
505 } else { | 506 } else { |
506 directLocals[local] = instruction; | 507 directLocals[local] = instruction; |
507 } | 508 } |
508 } | 509 } |
509 }); | 510 }); |
510 } | 511 } |
511 | 512 |
512 void enterLoopBody(LoopClosureRepresentationInfo loopInfo) { | 513 void enterLoopBody(ClosureBase loopInfo) { |
513 // If there are no declared boxed loop variables then we did not create the | 514 // If there are no declared boxed loop variables then we did not create the |
514 // box before the initializer and we have to create the box now. | 515 // box before the initializer and we have to create the box now. |
515 if (!loopInfo.hasBoxedVariables) { | 516 if (!loopInfo.hasBoxedVariables) { |
516 enterScope(loopInfo); | 517 enterScope(loopInfo); |
517 } | 518 } |
518 } | 519 } |
519 | 520 |
520 void enterLoopUpdates(LoopClosureRepresentationInfo loopInfo) { | 521 void enterLoopUpdates(ClosureBase loopInfo) { |
521 // If there are declared boxed loop variables then the updates might have | 522 // If there are declared boxed loop variables then the updates might have |
522 // access to the box and we must switch to a new box before executing the | 523 // access to the box and we must switch to a new box before executing the |
523 // updates. | 524 // updates. |
524 // In all other cases a new box will be created when entering the body of | 525 // In all other cases a new box will be created when entering the body of |
525 // the next iteration. | 526 // the next iteration. |
526 if (loopInfo.hasBoxedVariables) { | 527 if (loopInfo.hasBoxedVariables) { |
527 updateCaptureBox(loopInfo.context, loopInfo.boxedVariables); | 528 updateCaptureBox(loopInfo); |
528 } | 529 } |
529 } | 530 } |
530 | 531 |
531 /// Goes through the phis created in beginLoopHeader entry and adds the | 532 /// Goes through the phis created in beginLoopHeader entry and adds the |
532 /// input from the back edge (from the current value of directLocals) to them. | 533 /// input from the back edge (from the current value of directLocals) to them. |
533 void endLoop(HBasicBlock loopEntry) { | 534 void endLoop(HBasicBlock loopEntry) { |
534 // If the loop has an aborting body, we don't update the loop | 535 // If the loop has an aborting body, we don't update the loop |
535 // phis. | 536 // phis. |
536 if (loopEntry.predecessors.length == 1) return; | 537 if (loopEntry.predecessors.length == 1) return; |
537 loopEntry.forEachPhi((HPhi phi) { | 538 loopEntry.forEachPhi((HPhi phi) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 final MemberEntity memberContext; | 674 final MemberEntity memberContext; |
674 | 675 |
675 // Avoid slow Object.hashCode. | 676 // Avoid slow Object.hashCode. |
676 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); | 677 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); |
677 static int _nextHashCode = 0; | 678 static int _nextHashCode = 0; |
678 | 679 |
679 SyntheticLocal(this.name, this.executableContext, this.memberContext); | 680 SyntheticLocal(this.name, this.executableContext, this.memberContext); |
680 | 681 |
681 toString() => 'SyntheticLocal($name)'; | 682 toString() => 'SyntheticLocal($name)'; |
682 } | 683 } |
OLD | NEW |