| 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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables; | 123 cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables; |
| 124 | 124 |
| 125 /// Redirects accesses from element [from] to element [to]. The [to] element | 125 /// Redirects accesses from element [from] to element [to]. The [to] element |
| 126 /// must be a boxed variable or a variable that is stored in a closure-field. | 126 /// must be a boxed variable or a variable that is stored in a closure-field. |
| 127 void redirectElement(Local from, FieldEntity to) { | 127 void redirectElement(Local from, FieldEntity to) { |
| 128 assert(_redirectionMapping[from] == null); | 128 assert(_redirectionMapping[from] == null); |
| 129 _redirectionMapping[from] = to; | 129 _redirectionMapping[from] = to; |
| 130 assert(isStoredInClosureField(from) || isBoxed(from)); | 130 assert(isStoredInClosureField(from) || isBoxed(from)); |
| 131 } | 131 } |
| 132 | 132 |
| 133 HInstruction createBox() { | 133 HInstruction createBoxObject() { |
| 134 HInstruction box = new HCreateBox(commonMasks.nonNullType); | 134 HInstruction box = new HCreateBox(commonMasks.nonNullType); |
| 135 builder.add(box); | 135 builder.add(box); |
| 136 return box; | 136 return box; |
| 137 } | 137 } |
| 138 | 138 |
| 139 /// If the scope (function or loop) [node] has captured variables then this | 139 /// If the scope (function or loop) [node] has captured variables then this |
| 140 /// method creates a box and sets up the redirections. | 140 /// method creates a box and sets up the redirections. |
| 141 void enterScope(CapturedScope closureInfo, | 141 void enterScope(CapturedScope closureInfo, |
| 142 {bool forGenerativeConstructorBody: false}) { | 142 {bool forGenerativeConstructorBody: false}) { |
| 143 // See if any variable in the top-scope of the function is captured. If yes | 143 // See if any variable in the top-scope of the function is captured. If yes |
| 144 // we need to create a box-object. | 144 // we need to create a box-object. |
| 145 if (!closureInfo.requiresContextBox) return; | 145 if (!closureInfo.hasBox) return; |
| 146 HInstruction box; | 146 HInstruction boxObject; |
| 147 // The scope has captured variables. | 147 // The scope has captured variables. |
| 148 if (forGenerativeConstructorBody) { | 148 if (forGenerativeConstructorBody) { |
| 149 // The box is passed as a parameter to a generative | 149 // The box is passed as a parameter to a generative |
| 150 // constructor body. | 150 // constructor body. |
| 151 box = builder.addParameter(closureInfo.context, commonMasks.nonNullType); | 151 boxObject = |
| 152 builder.addParameter(closureInfo.box, commonMasks.nonNullType); |
| 152 } else { | 153 } else { |
| 153 box = createBox(); | 154 boxObject = createBoxObject(); |
| 154 } | 155 } |
| 155 // Add the box to the known locals. | 156 // Add the box to the known locals. |
| 156 directLocals[closureInfo.context] = box; | 157 directLocals[closureInfo.box] = boxObject; |
| 157 // Make sure that accesses to the boxed locals go into the box. We also | 158 // Make sure that accesses to the boxed locals go into the box. We also |
| 158 // need to make sure that parameters are copied into the box if necessary. | 159 // need to make sure that parameters are copied into the box if necessary. |
| 159 closureInfo.forEachBoxedVariable((_from, _to) { | 160 closureInfo.forEachBoxedVariable((_from, _to) { |
| 160 Local from = _from; | 161 Local from = _from; |
| 161 FieldEntity to = _to; | 162 FieldEntity to = _to; |
| 162 // The [from] can only be a parameter for function-scopes and not | 163 // The [from] can only be a parameter for function-scopes and not |
| 163 // loop scopes. | 164 // loop scopes. |
| 164 bool isParameter = | 165 bool isParameter = |
| 165 // TODO(johnniwinther): Avoid this hack. Maybe [Local] should have an | 166 // TODO(johnniwinther): Avoid this hack. Maybe [Local] should have an |
| 166 // [isParameter] property? | 167 // [isParameter] property? |
| (...skipping 16 matching lines...) Expand all Loading... |
| 183 } | 184 } |
| 184 }); | 185 }); |
| 185 } | 186 } |
| 186 | 187 |
| 187 /// Replaces the current box with a new box and copies over the given list | 188 /// Replaces the current box with a new box and copies over the given list |
| 188 /// of elements from the old box into the new box. | 189 /// of elements from the old box into the new box. |
| 189 void updateCaptureBox(Local currentBox, List<Local> toBeCopiedElements) { | 190 void updateCaptureBox(Local currentBox, List<Local> toBeCopiedElements) { |
| 190 // Create a new box and copy over the values from the old box into the | 191 // Create a new box and copy over the values from the old box into the |
| 191 // new one. | 192 // new one. |
| 192 HInstruction oldBox = readLocal(currentBox); | 193 HInstruction oldBox = readLocal(currentBox); |
| 193 HInstruction newBox = createBox(); | 194 HInstruction newBox = createBoxObject(); |
| 194 for (Local boxedVariable in toBeCopiedElements) { | 195 for (Local boxedVariable in toBeCopiedElements) { |
| 195 // [readLocal] uses the [currentBox] to find its box. By replacing it | 196 // [readLocal] uses the [currentBox] to find its box. By replacing it |
| 196 // behind its back we can still get to the old values. | 197 // behind its back we can still get to the old values. |
| 197 updateLocal(currentBox, oldBox); | 198 updateLocal(currentBox, oldBox); |
| 198 HInstruction oldValue = readLocal(boxedVariable); | 199 HInstruction oldValue = readLocal(boxedVariable); |
| 199 updateLocal(currentBox, newBox); | 200 updateLocal(currentBox, newBox); |
| 200 updateLocal(boxedVariable, oldValue); | 201 updateLocal(boxedVariable, oldValue); |
| 201 } | 202 } |
| 202 updateLocal(currentBox, newBox); | 203 updateLocal(currentBox, newBox); |
| 203 } | 204 } |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 } | 545 } |
| 545 } | 546 } |
| 546 | 547 |
| 547 void enterLoopUpdates(CapturedLoopScope loopInfo) { | 548 void enterLoopUpdates(CapturedLoopScope loopInfo) { |
| 548 // If there are declared boxed loop variables then the updates might have | 549 // If there are declared boxed loop variables then the updates might have |
| 549 // access to the box and we must switch to a new box before executing the | 550 // access to the box and we must switch to a new box before executing the |
| 550 // updates. | 551 // updates. |
| 551 // In all other cases a new box will be created when entering the body of | 552 // In all other cases a new box will be created when entering the body of |
| 552 // the next iteration. | 553 // the next iteration. |
| 553 if (loopInfo.hasBoxedLoopVariables) { | 554 if (loopInfo.hasBoxedLoopVariables) { |
| 554 updateCaptureBox(loopInfo.context, loopInfo.boxedLoopVariables); | 555 updateCaptureBox(loopInfo.box, loopInfo.boxedLoopVariables); |
| 555 } | 556 } |
| 556 } | 557 } |
| 557 | 558 |
| 558 /// Goes through the phis created in beginLoopHeader entry and adds the | 559 /// Goes through the phis created in beginLoopHeader entry and adds the |
| 559 /// input from the back edge (from the current value of directLocals) to them. | 560 /// input from the back edge (from the current value of directLocals) to them. |
| 560 void endLoop(HBasicBlock loopEntry) { | 561 void endLoop(HBasicBlock loopEntry) { |
| 561 // If the loop has an aborting body, we don't update the loop | 562 // If the loop has an aborting body, we don't update the loop |
| 562 // phis. | 563 // phis. |
| 563 if (loopEntry.predecessors.length == 1) return; | 564 if (loopEntry.predecessors.length == 1) return; |
| 564 loopEntry.forEachPhi((HPhi phi) { | 565 loopEntry.forEachPhi((HPhi phi) { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 final MemberEntity memberContext; | 701 final MemberEntity memberContext; |
| 701 | 702 |
| 702 // Avoid slow Object.hashCode. | 703 // Avoid slow Object.hashCode. |
| 703 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); | 704 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); |
| 704 static int _nextHashCode = 0; | 705 static int _nextHashCode = 0; |
| 705 | 706 |
| 706 SyntheticLocal(this.name, this.executableContext, this.memberContext); | 707 SyntheticLocal(this.name, this.executableContext, this.memberContext); |
| 707 | 708 |
| 708 toString() => 'SyntheticLocal($name)'; | 709 toString() => 'SyntheticLocal($name)'; |
| 709 } | 710 } |
| OLD | NEW |