Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(498)

Side by Side Diff: pkg/compiler/lib/src/js_model/closure_visitors.dart

Issue 2994353002: Fix the locals lookup of variables and partial implementation of boxing of variables.
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_model/closure.dart ('k') | pkg/compiler/lib/src/js_model/elements.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 'closure.dart'; 8 import 'closure.dart';
9 9
10 /// This builder walks the code to determine what variables are captured/free at 10 /// This builder walks the code to determine what variables are captured/free at
11 /// various points to build CapturedScope that can respond to queries 11 /// various points to build CapturedScope that can respond to queries
12 /// about how a particular variable is being used at any point in the code. 12 /// about how a particular variable is being used at any point in the code.
13 class CapturedScopeBuilder extends ir.Visitor { 13 class CapturedScopeBuilder extends ir.Visitor {
14 ir.TreeNode _currentLocalFunction;
15
16 ScopeModel _model; 14 ScopeModel _model;
17 15
18 /// A map of each visited call node with the associated information about what 16 /// A map of each visited call node with the associated information about what
19 /// variables are captured/used. Each ir.Node key corresponds to a scope that 17 /// variables are captured/used. Each ir.Node key corresponds to a scope that
20 /// was encountered while visiting a closure (initially called through 18 /// was encountered while visiting a closure (initially called through
21 /// [translateLazyIntializer] or [translateConstructorOrProcedure]). 19 /// [translateLazyIntializer] or [translateConstructorOrProcedure]).
22 Map<ir.Node, KernelCapturedScope> get _scopesCapturedInClosureMap => 20 Map<ir.Node, KernelCapturedScope> get _scopesCapturedInClosureMap =>
23 _model.capturedScopesMap; 21 _model.capturedScopesMap;
24 22
25 /// A map of the nodes that we have flagged as necessary to generate closure 23 /// A map of the nodes that we have flagged as necessary to generate closure
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 61
64 /// Keeps track of the number of boxes that we've created so that they each 62 /// Keeps track of the number of boxes that we've created so that they each
65 /// have unique names. 63 /// have unique names.
66 int _boxCounter = 0; 64 int _boxCounter = 0;
67 65
68 CapturedScopeBuilder(this._model, {bool hasThisLocal}) 66 CapturedScopeBuilder(this._model, {bool hasThisLocal})
69 : this._hasThisLocal = hasThisLocal; 67 : this._hasThisLocal = hasThisLocal;
70 68
71 /// Update the [CapturedScope] object corresponding to 69 /// Update the [CapturedScope] object corresponding to
72 /// this node if any variables are captured. 70 /// this node if any variables are captured.
73 void attachCapturedScopeVariables(ir.Node node) { 71 void attachCapturedScopeVariables(ir.TreeNode node) {
74 Set<ir.VariableDeclaration> capturedVariablesForScope = 72 Set<ir.VariableDeclaration> capturedVariablesForScope =
75 new Set<ir.VariableDeclaration>(); 73 new Set<ir.VariableDeclaration>();
76 74
77 for (ir.VariableDeclaration variable in _scopeVariables) { 75 for (ir.VariableDeclaration variable in _scopeVariables) {
78 // No need to box non-assignable elements. 76 // No need to box non-assignable elements.
79 if (variable.isFinal || variable.isConst) continue; 77 if (variable.isFinal || variable.isConst) continue;
80 if (!_mutatedVariables.contains(variable)) continue; 78 if (!_mutatedVariables.contains(variable)) continue;
81 if (_capturedVariables.contains(variable)) { 79 if (_capturedVariables.contains(variable)) {
82 capturedVariablesForScope.add(variable); 80 capturedVariablesForScope.add(variable);
83 } 81 }
84 } 82 }
85 if (!capturedVariablesForScope.isEmpty) { 83 if (!capturedVariablesForScope.isEmpty) {
86 assert(_model.scopeInfo != null); 84 assert(_model.scopeInfo != null);
87 assert(_currentLocalFunction != null);
88 KernelScopeInfo from = _model.scopeInfo; 85 KernelScopeInfo from = _model.scopeInfo;
89 _scopesCapturedInClosureMap[node] = new KernelCapturedScope( 86 var capturedScope = new KernelCapturedScope(
90 capturedVariablesForScope, 87 capturedVariablesForScope,
91 new NodeBox(getBoxName(), _executableContext), 88 new NodeBox(getBoxName(), _executableContext),
92 _currentLocalFunction,
93 from.localsUsedInTryOrSync, 89 from.localsUsedInTryOrSync,
94 from.freeVariables, 90 from.freeVariables,
95 _hasThisLocal); 91 _hasThisLocal);
92 _model.scopeInfo =
93 _scopesCapturedInClosureMap[node.parent] = capturedScope;
94 _currentScopeInfo.capturedScopes.add(node.parent);
95 print(
96 'FUUUUUUUUUUUUUUUUUUU ${node.parent} ${_executableContext.parent} $_cu rrentScopeInfo');
96 } 97 }
97 } 98 }
98 99
99 /// Generate a unique name for the [_boxCounter]th box field. 100 /// Generate a unique name for the [_boxCounter]th box field.
100 /// 101 ///
101 /// The result is used as the name of [NodeBox]s and [BoxLocal]s, and must 102 /// The result is used as the name of [NodeBox]s and [BoxLocal]s, and must
102 /// therefore be unique to avoid breaking an invariant in the element model 103 /// therefore be unique to avoid breaking an invariant in the element model
103 /// (classes cannot declare multiple fields with the same name). 104 /// (classes cannot declare multiple fields with the same name).
104 /// 105 ///
105 /// Also, the names should be distinct from real field names to prevent 106 /// Also, the names should be distinct from real field names to prevent
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 _markVariableAsUsed(node.variable); 148 _markVariableAsUsed(node.variable);
148 } 149 }
149 150
150 @override 151 @override
151 visitVariableSet(ir.VariableSet node) { 152 visitVariableSet(ir.VariableSet node) {
152 _mutatedVariables.add(node.variable); 153 _mutatedVariables.add(node.variable);
153 _markVariableAsUsed(node.variable); 154 _markVariableAsUsed(node.variable);
154 node.visitChildren(this); 155 node.visitChildren(this);
155 } 156 }
156 157
158 @override
159 visitVariableDeclaration(ir.VariableDeclaration declaration) {
160 if (!declaration.isFieldFormal) {
161 _scopeVariables.add(declaration);
162 }
163
164 if (declaration.initializer != null) {
165 declaration.initializer.accept(this);
166 }
167 }
168
157 /// Add this variable to the set of free variables if appropriate and add to 169 /// Add this variable to the set of free variables if appropriate and add to
158 /// the tally of variables used in try or sync blocks. 170 /// the tally of variables used in try or sync blocks.
159 void _markVariableAsUsed(ir.VariableDeclaration variable) { 171 void _markVariableAsUsed(ir.VariableDeclaration variable) {
160 if (_isInsideClosure && !_inCurrentContext(variable)) { 172 if (_isInsideClosure && !_inCurrentContext(variable)) {
161 // If the element is not declared in the current function and the element 173 // 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. 174 // 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 175 // Note that the check on [insideClosure] is not just an
164 // optimization: factories have type parameters as function 176 // optimization: factories have type parameters as function
165 // parameters, and type parameters are declared in the class, not 177 // parameters, and type parameters are declared in the class, not
166 // the factory. 178 // the factory.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 boxedLoopVariables.add(variable); 218 boxedLoopVariables.add(variable);
207 } 219 }
208 } 220 }
209 }); 221 });
210 KernelCapturedScope scope = _scopesCapturedInClosureMap[node]; 222 KernelCapturedScope scope = _scopesCapturedInClosureMap[node];
211 if (scope == null) return; 223 if (scope == null) return;
212 _scopesCapturedInClosureMap[node] = new KernelCapturedLoopScope( 224 _scopesCapturedInClosureMap[node] = new KernelCapturedLoopScope(
213 scope.boxedVariables, 225 scope.boxedVariables,
214 scope.capturedVariablesAccessor, 226 scope.capturedVariablesAccessor,
215 boxedLoopVariables, 227 boxedLoopVariables,
216 scope.context,
217 scope.localsUsedInTryOrSync, 228 scope.localsUsedInTryOrSync,
218 scope.freeVariables, 229 scope.freeVariables,
219 scope.hasThisLocal); 230 scope.hasThisLocal);
220 } 231 }
221 232
222 void visitInvokable(ir.TreeNode node) { 233 void visitInvokable(ir.TreeNode node) {
223 bool oldIsInsideClosure = _isInsideClosure; 234 bool oldIsInsideClosure = _isInsideClosure;
224 ir.TreeNode oldExecutableContext = _executableContext; 235 ir.TreeNode oldExecutableContext = _executableContext;
225 KernelScopeInfo oldScopeInfo = _currentScopeInfo; 236 KernelScopeInfo oldScopeInfo = _currentScopeInfo;
226 ir.TreeNode oldLocalFunction = _currentLocalFunction;
227 237
228 // _outermostNode is only null the first time we enter the body of the 238 // _outermostNode is only null the first time we enter the body of the
229 // field, constructor, or method that is being analyzed. 239 // field, constructor, or method that is being analyzed.
230 _isInsideClosure = _outermostNode != null; 240 _isInsideClosure = _outermostNode != null;
231 _executableContext = node; 241 _executableContext = node;
232 242
233 _currentScopeInfo = new KernelScopeInfo(_hasThisLocal); 243 _currentScopeInfo = new KernelScopeInfo(_hasThisLocal);
234 if (_isInsideClosure) { 244 if (_isInsideClosure) {
235 _closuresToGenerate[node] = _currentScopeInfo; 245 _closuresToGenerate[node] = _currentScopeInfo;
236 _currentLocalFunction = node.parent; 246 print("EEEEEEEEEEEEEEEeee $_currentScopeInfo");
237 } else { 247 } else {
238 _outermostNode = node; 248 _outermostNode = node;
239 _model.scopeInfo = _currentScopeInfo;
240 } 249 }
250 _model.scopeInfo = _currentScopeInfo;
241 251
242 enterNewScope(node, () { 252 enterNewScope(node, () {
243 node.visitChildren(this); 253 node.visitChildren(this);
244 }); 254 });
245 255
246 KernelScopeInfo savedScopeInfo = _currentScopeInfo; 256 KernelScopeInfo savedScopeInfo = _currentScopeInfo;
247 bool savedIsInsideClosure = _isInsideClosure; 257 bool savedIsInsideClosure = _isInsideClosure;
248 258
249 // Restore old values. 259 // Restore old values.
250 _isInsideClosure = oldIsInsideClosure; 260 _isInsideClosure = oldIsInsideClosure;
251 _currentScopeInfo = oldScopeInfo; 261 _currentScopeInfo = oldScopeInfo;
252 _executableContext = oldExecutableContext; 262 _executableContext = oldExecutableContext;
253 _currentLocalFunction = oldLocalFunction;
254 263
255 // Mark all free variables as captured and expect to encounter them in the 264 // Mark all free variables as captured and expect to encounter them in the
256 // outer function. 265 // outer function.
257 Iterable<ir.VariableDeclaration> freeVariables = 266 Iterable<ir.VariableDeclaration> freeVariables =
258 savedScopeInfo.freeVariables; 267 savedScopeInfo.freeVariables;
259 assert(freeVariables.isEmpty || savedIsInsideClosure); 268 assert(freeVariables.isEmpty || savedIsInsideClosure);
260 for (ir.VariableDeclaration freeVariable in freeVariables) { 269 for (ir.VariableDeclaration freeVariable in freeVariables) {
261 _capturedVariables.add(freeVariable); 270 _capturedVariables.add(freeVariable);
262 _markVariableAsUsed(freeVariable); 271 _markVariableAsUsed(freeVariable);
263 } 272 }
(...skipping 14 matching lines...) Expand all
278 } 287 }
279 288
280 void translateConstructorOrProcedure(ir.Node constructorOrProcedure) { 289 void translateConstructorOrProcedure(ir.Node constructorOrProcedure) {
281 constructorOrProcedure.accept(this); 290 constructorOrProcedure.accept(this);
282 } 291 }
283 292
284 void visitFunctionNode(ir.FunctionNode functionNode) { 293 void visitFunctionNode(ir.FunctionNode functionNode) {
285 visitInvokable(functionNode); 294 visitInvokable(functionNode);
286 } 295 }
287 } 296 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_model/closure.dart ('k') | pkg/compiler/lib/src/js_model/elements.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698