| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../closure.dart'; | 7 import '../closure.dart'; |
| 8 import '../elements/entities.dart'; | 8 import '../elements/entities.dart'; |
| 9 import '../kernel/element_map.dart'; | 9 import '../kernel/element_map.dart'; |
| 10 import 'closure.dart'; | 10 import 'closure.dart'; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 /// If true, the visitor is currently traversing some nodes that are inside a | 59 /// If true, the visitor is currently traversing some nodes that are inside a |
| 60 /// try block. | 60 /// try block. |
| 61 bool _inTry = false; | 61 bool _inTry = false; |
| 62 | 62 |
| 63 /// Lookup the local entity that corresponds to a kernel variable declaration. | 63 /// Lookup the local entity that corresponds to a kernel variable declaration. |
| 64 final KernelToLocalsMap _localsMap; | 64 final KernelToLocalsMap _localsMap; |
| 65 | 65 |
| 66 /// The current scope we are in. | 66 /// The current scope we are in. |
| 67 KernelScopeInfo _currentScopeInfo; | 67 KernelScopeInfo _currentScopeInfo; |
| 68 | 68 |
| 69 // TODO(johnniwinther): Remove the need for this. | |
| 70 final KernelToElementMap _kernelToElementMap; | |
| 71 | |
| 72 final Entity _thisLocal; | 69 final Entity _thisLocal; |
| 73 | 70 |
| 74 CapturedScopeBuilder( | 71 CapturedScopeBuilder(this._currentMember, this._scopesCapturedInClosureMap, |
| 75 this._currentMember, | 72 this._scopeInfoMap, this._closuresToGenerate, this._localsMap) |
| 76 this._scopesCapturedInClosureMap, | |
| 77 this._scopeInfoMap, | |
| 78 this._closuresToGenerate, | |
| 79 this._localsMap, | |
| 80 this._kernelToElementMap) | |
| 81 : this._thisLocal = | 73 : this._thisLocal = |
| 82 _currentMember.isInstanceMember || _currentMember.isConstructor | 74 _currentMember.isInstanceMember || _currentMember.isConstructor |
| 83 ? new ThisLocal(_currentMember) | 75 ? new ThisLocal(_currentMember) |
| 84 : null; | 76 : null; |
| 85 | 77 |
| 86 /// Update the [CapturedScope] object corresponding to | 78 /// Update the [CapturedScope] object corresponding to |
| 87 /// this node if any variables are captured. | 79 /// this node if any variables are captured. |
| 88 void attachCapturedScopeVariables(ir.Node node) { | 80 void attachCapturedScopeVariables(ir.Node node) { |
| 89 Set<Local> capturedVariablesForScope = new Set<Local>(); | 81 Set<Local> capturedVariablesForScope = new Set<Local>(); |
| 90 | 82 |
| 91 for (ir.VariableDeclaration variable in _scopeVariables) { | 83 for (ir.VariableDeclaration variable in _scopeVariables) { |
| 92 // No need to box non-assignable elements. | 84 // No need to box non-assignable elements. |
| 93 if (variable.isFinal || variable.isConst) continue; | 85 if (variable.isFinal || variable.isConst) continue; |
| 94 if (!_mutatedVariables.contains(variable)) continue; | 86 if (!_mutatedVariables.contains(variable)) continue; |
| 95 if (_capturedVariables.contains(variable)) { | 87 if (_capturedVariables.contains(variable)) { |
| 96 capturedVariablesForScope.add(_localsMap.getLocal(variable)); | 88 capturedVariablesForScope.add(_localsMap.getLocalVariable(variable)); |
| 97 } | 89 } |
| 98 } | 90 } |
| 99 if (!capturedVariablesForScope.isEmpty) { | 91 if (!capturedVariablesForScope.isEmpty) { |
| 100 assert(_scopeInfoMap[_currentMember] != null); | 92 assert(_scopeInfoMap[_currentMember] != null); |
| 101 assert(_currentLocalFunction != null); | 93 assert(_currentLocalFunction != null); |
| 102 KernelScopeInfo from = _scopeInfoMap[_currentMember]; | 94 KernelScopeInfo from = _scopeInfoMap[_currentMember]; |
| 103 _scopesCapturedInClosureMap[node] = new KernelCapturedScope( | 95 _scopesCapturedInClosureMap[node] = new KernelCapturedScope( |
| 104 capturedVariablesForScope, | 96 capturedVariablesForScope, |
| 105 _currentLocalFunction, | 97 _currentLocalFunction, |
| 106 from.localsUsedInTryOrSync, | 98 from.localsUsedInTryOrSync, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 // If the element is not declared in the current function and the element | 153 // If the element is not declared in the current function and the element |
| 162 // is not the closure itself we need to mark the element as free variable. | 154 // is not the closure itself we need to mark the element as free variable. |
| 163 // Note that the check on [insideClosure] is not just an | 155 // Note that the check on [insideClosure] is not just an |
| 164 // optimization: factories have type parameters as function | 156 // optimization: factories have type parameters as function |
| 165 // parameters, and type parameters are declared in the class, not | 157 // parameters, and type parameters are declared in the class, not |
| 166 // the factory. | 158 // the factory. |
| 167 _currentScopeInfo.freeVariables.add(variable); | 159 _currentScopeInfo.freeVariables.add(variable); |
| 168 } | 160 } |
| 169 if (_inTry) { | 161 if (_inTry) { |
| 170 _currentScopeInfo.localsUsedInTryOrSync | 162 _currentScopeInfo.localsUsedInTryOrSync |
| 171 .add(_localsMap.getLocal(variable)); | 163 .add(_localsMap.getLocalVariable(variable)); |
| 172 } | 164 } |
| 173 } | 165 } |
| 174 | 166 |
| 175 @override | 167 @override |
| 176 void visitForStatement(ir.ForStatement node) { | 168 void visitForStatement(ir.ForStatement node) { |
| 177 List<Local> boxedLoopVariables = <Local>[]; | 169 List<Local> boxedLoopVariables = <Local>[]; |
| 178 enterNewScope(node, () { | 170 enterNewScope(node, () { |
| 179 // First visit initialized variables and update steps so we can easily | 171 // First visit initialized variables and update steps so we can easily |
| 180 // check if a loop variable was captured in one of these subexpressions. | 172 // check if a loop variable was captured in one of these subexpressions. |
| 181 node.variables | 173 node.variables |
| (...skipping 14 matching lines...) Expand all Loading... |
| 196 // condition or body are indeed flagged as mutated. | 188 // condition or body are indeed flagged as mutated. |
| 197 if (node.condition != null) node.condition.accept(this); | 189 if (node.condition != null) node.condition.accept(this); |
| 198 node.body.accept(this); | 190 node.body.accept(this); |
| 199 | 191 |
| 200 // See if we have declared loop variables that need to be boxed. | 192 // See if we have declared loop variables that need to be boxed. |
| 201 for (ir.VariableDeclaration variable in node.variables) { | 193 for (ir.VariableDeclaration variable in node.variables) { |
| 202 // Non-mutated variables should not be boxed. The _mutatedVariables set | 194 // Non-mutated variables should not be boxed. The _mutatedVariables set |
| 203 // gets cleared when `enterNewScope` returns, so check it here. | 195 // gets cleared when `enterNewScope` returns, so check it here. |
| 204 if (_capturedVariables.contains(variable) && | 196 if (_capturedVariables.contains(variable) && |
| 205 _mutatedVariables.contains(variable)) { | 197 _mutatedVariables.contains(variable)) { |
| 206 boxedLoopVariables.add(_localsMap.getLocal(variable)); | 198 boxedLoopVariables.add(_localsMap.getLocalVariable(variable)); |
| 207 } | 199 } |
| 208 } | 200 } |
| 209 }); | 201 }); |
| 210 KernelCapturedScope scope = _scopesCapturedInClosureMap[node]; | 202 KernelCapturedScope scope = _scopesCapturedInClosureMap[node]; |
| 211 if (scope == null) return; | 203 if (scope == null) return; |
| 212 _scopesCapturedInClosureMap[node] = new KernelCapturedLoopScope( | 204 _scopesCapturedInClosureMap[node] = new KernelCapturedLoopScope( |
| 213 scope.boxedVariables, | 205 scope.boxedVariables, |
| 214 boxedLoopVariables, | 206 boxedLoopVariables, |
| 215 scope.context, | 207 scope.context, |
| 216 scope.localsUsedInTryOrSync, | 208 scope.localsUsedInTryOrSync, |
| 217 scope.freeVariables, | 209 scope.freeVariables, |
| 218 _localsMap, | 210 _localsMap, |
| 219 scope.thisLocal); | 211 scope.thisLocal); |
| 220 } | 212 } |
| 221 | 213 |
| 222 void visitInvokable(ir.TreeNode node) { | 214 void visitInvokable(ir.TreeNode node) { |
| 223 bool oldIsInsideClosure = _isInsideClosure; | 215 bool oldIsInsideClosure = _isInsideClosure; |
| 224 ir.Node oldExecutableContext = _executableContext; | 216 ir.Node oldExecutableContext = _executableContext; |
| 225 KernelScopeInfo oldScopeInfo = _currentScopeInfo; | 217 KernelScopeInfo oldScopeInfo = _currentScopeInfo; |
| 226 Local oldLocalFunction = _currentLocalFunction; | 218 Local oldLocalFunction = _currentLocalFunction; |
| 227 | 219 |
| 228 // _outermostNode is only null the first time we enter the body of the | 220 // _outermostNode is only null the first time we enter the body of the |
| 229 // field, constructor, or method that is being analyzed. | 221 // field, constructor, or method that is being analyzed. |
| 230 _isInsideClosure = _outermostNode != null; | 222 _isInsideClosure = _outermostNode != null; |
| 231 _executableContext = node; | 223 _executableContext = node; |
| 232 | 224 |
| 233 _currentScopeInfo = new KernelScopeInfo(_thisLocal, _localsMap); | 225 _currentScopeInfo = new KernelScopeInfo(_thisLocal, _localsMap); |
| 234 if (_isInsideClosure) { | 226 if (_isInsideClosure) { |
| 235 _closuresToGenerate[node] = _currentScopeInfo; | 227 _closuresToGenerate[node] = _currentScopeInfo; |
| 236 _currentLocalFunction = _kernelToElementMap.getLocalFunction(node.parent); | 228 _currentLocalFunction = _localsMap.getLocalFunction(node.parent); |
| 237 } else { | 229 } else { |
| 238 _outermostNode = node; | 230 _outermostNode = node; |
| 239 _scopeInfoMap[_currentMember] = _currentScopeInfo; | 231 _scopeInfoMap[_currentMember] = _currentScopeInfo; |
| 240 } | 232 } |
| 241 | 233 |
| 242 enterNewScope(node, () { | 234 enterNewScope(node, () { |
| 243 node.visitChildren(this); | 235 node.visitChildren(this); |
| 244 }); | 236 }); |
| 245 | 237 |
| 246 KernelScopeInfo savedScopeInfo = _currentScopeInfo; | 238 KernelScopeInfo savedScopeInfo = _currentScopeInfo; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 } | 271 } |
| 280 | 272 |
| 281 void translateConstructorOrProcedure(ir.Node constructorOrProcedure) { | 273 void translateConstructorOrProcedure(ir.Node constructorOrProcedure) { |
| 282 constructorOrProcedure.accept(this); | 274 constructorOrProcedure.accept(this); |
| 283 } | 275 } |
| 284 | 276 |
| 285 void visitFunctionNode(ir.FunctionNode functionNode) { | 277 void visitFunctionNode(ir.FunctionNode functionNode) { |
| 286 visitInvokable(functionNode); | 278 visitInvokable(functionNode); |
| 287 } | 279 } |
| 288 } | 280 } |
| OLD | NEW |