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

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

Issue 3007743002: Add boxing for modified variables (Closed)
Patch Set: merged with master Created 3 years, 3 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
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 var capturedScope = 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);
96 _model.scopeInfo = _scopesCapturedInClosureMap[node] = capturedScope; 92 _model.scopeInfo = _scopesCapturedInClosureMap[node] = capturedScope;
97 } 93 }
98 } 94 }
99 95
100 /// Generate a unique name for the [_boxCounter]th box field. 96 /// Generate a unique name for the [_boxCounter]th box field.
101 /// 97 ///
102 /// The result is used as the name of [NodeBox]s and [BoxLocal]s, and must 98 /// The result is used as the name of [NodeBox]s and [BoxLocal]s, and must
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 _markVariableAsUsed(node.variable); 144 _markVariableAsUsed(node.variable);
149 } 145 }
150 146
151 @override 147 @override
152 visitVariableSet(ir.VariableSet node) { 148 visitVariableSet(ir.VariableSet node) {
153 _mutatedVariables.add(node.variable); 149 _mutatedVariables.add(node.variable);
154 _markVariableAsUsed(node.variable); 150 _markVariableAsUsed(node.variable);
155 node.visitChildren(this); 151 node.visitChildren(this);
156 } 152 }
157 153
154 @override
155 visitVariableDeclaration(ir.VariableDeclaration declaration) {
156 if (!declaration.isFieldFormal) {
157 _scopeVariables.add(declaration);
158 }
159
160 declaration.visitChildren(this);
161 }
162
158 /// Add this variable to the set of free variables if appropriate and add to 163 /// Add this variable to the set of free variables if appropriate and add to
159 /// the tally of variables used in try or sync blocks. 164 /// the tally of variables used in try or sync blocks.
160 void _markVariableAsUsed(ir.VariableDeclaration variable) { 165 void _markVariableAsUsed(ir.VariableDeclaration variable) {
161 if (_isInsideClosure && !_inCurrentContext(variable)) { 166 if (_isInsideClosure && !_inCurrentContext(variable)) {
162 // If the element is not declared in the current function and the element 167 // If the element is not declared in the current function and the element
163 // is not the closure itself we need to mark the element as free variable. 168 // is not the closure itself we need to mark the element as free variable.
164 // Note that the check on [insideClosure] is not just an 169 // Note that the check on [insideClosure] is not just an
165 // optimization: factories have type parameters as function 170 // optimization: factories have type parameters as function
166 // parameters, and type parameters are declared in the class, not 171 // parameters, and type parameters are declared in the class, not
167 // the factory. 172 // the factory.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 boxedLoopVariables.add(variable); 212 boxedLoopVariables.add(variable);
208 } 213 }
209 } 214 }
210 }); 215 });
211 KernelCapturedScope scope = _scopesCapturedInClosureMap[node]; 216 KernelCapturedScope scope = _scopesCapturedInClosureMap[node];
212 if (scope == null) return; 217 if (scope == null) return;
213 _scopesCapturedInClosureMap[node] = new KernelCapturedLoopScope( 218 _scopesCapturedInClosureMap[node] = new KernelCapturedLoopScope(
214 scope.boxedVariables, 219 scope.boxedVariables,
215 scope.capturedVariablesAccessor, 220 scope.capturedVariablesAccessor,
216 boxedLoopVariables, 221 boxedLoopVariables,
217 scope.context,
218 scope.localsUsedInTryOrSync, 222 scope.localsUsedInTryOrSync,
219 scope.freeVariables, 223 scope.freeVariables,
220 scope.hasThisLocal); 224 scope.hasThisLocal);
221 } 225 }
222 226
223 void visitInvokable(ir.TreeNode node) { 227 void visitInvokable(ir.TreeNode node) {
224 assert(node is ir.Member || 228 assert(node is ir.Member ||
225 node is ir.FunctionExpression || 229 node is ir.FunctionExpression ||
226 node is ir.FunctionDeclaration); 230 node is ir.FunctionDeclaration);
227 bool oldIsInsideClosure = _isInsideClosure; 231 bool oldIsInsideClosure = _isInsideClosure;
228 ir.TreeNode oldExecutableContext = _executableContext; 232 ir.TreeNode oldExecutableContext = _executableContext;
229 KernelScopeInfo oldScopeInfo = _currentScopeInfo; 233 KernelScopeInfo oldScopeInfo = _currentScopeInfo;
230 ir.TreeNode oldLocalFunction = _currentLocalFunction;
231 234
232 // _outermostNode is only null the first time we enter the body of the 235 // _outermostNode is only null the first time we enter the body of the
233 // field, constructor, or method that is being analyzed. 236 // field, constructor, or method that is being analyzed.
234 _isInsideClosure = _outermostNode != null; 237 _isInsideClosure = _outermostNode != null;
235 _executableContext = node; 238 _executableContext = node;
236 239
237 _currentScopeInfo = new KernelScopeInfo(_hasThisLocal); 240 _currentScopeInfo = new KernelScopeInfo(_hasThisLocal);
238 if (_isInsideClosure) { 241 if (_isInsideClosure) {
239 _closuresToGenerate[node] = _currentScopeInfo; 242 _closuresToGenerate[node] = _currentScopeInfo;
240 _currentLocalFunction = node.parent;
241 } else { 243 } else {
242 _outermostNode = node; 244 _outermostNode = node;
243 } 245 }
244 _model.scopeInfo = _currentScopeInfo; 246 _model.scopeInfo = _currentScopeInfo;
245 247
246 enterNewScope(node, () { 248 enterNewScope(node, () {
247 node.visitChildren(this); 249 node.visitChildren(this);
248 }); 250 });
249 251
250 KernelScopeInfo savedScopeInfo = _currentScopeInfo; 252 KernelScopeInfo savedScopeInfo = _currentScopeInfo;
251 bool savedIsInsideClosure = _isInsideClosure; 253 bool savedIsInsideClosure = _isInsideClosure;
252 254
253 // Restore old values. 255 // Restore old values.
254 _isInsideClosure = oldIsInsideClosure; 256 _isInsideClosure = oldIsInsideClosure;
255 _currentScopeInfo = oldScopeInfo; 257 _currentScopeInfo = oldScopeInfo;
256 _executableContext = oldExecutableContext; 258 _executableContext = oldExecutableContext;
257 _currentLocalFunction = oldLocalFunction;
258 259
259 // Mark all free variables as captured and expect to encounter them in the 260 // Mark all free variables as captured and expect to encounter them in the
260 // outer function. 261 // outer function.
261 Iterable<ir.VariableDeclaration> freeVariables = 262 Iterable<ir.VariableDeclaration> freeVariables =
262 savedScopeInfo.freeVariables; 263 savedScopeInfo.freeVariables;
263 assert(freeVariables.isEmpty || savedIsInsideClosure); 264 assert(freeVariables.isEmpty || savedIsInsideClosure);
264 for (ir.VariableDeclaration freeVariable in freeVariables) { 265 for (ir.VariableDeclaration freeVariable in freeVariables) {
265 _capturedVariables.add(freeVariable); 266 _capturedVariables.add(freeVariable);
266 _markVariableAsUsed(freeVariable); 267 _markVariableAsUsed(freeVariable);
267 } 268 }
(...skipping 27 matching lines...) Expand all
295 @override 296 @override
296 void visitFunctionExpression(ir.FunctionExpression functionExpression) { 297 void visitFunctionExpression(ir.FunctionExpression functionExpression) {
297 visitInvokable(functionExpression); 298 visitInvokable(functionExpression);
298 } 299 }
299 300
300 @override 301 @override
301 void visitFunctionDeclaration(ir.FunctionDeclaration functionDeclaration) { 302 void visitFunctionDeclaration(ir.FunctionDeclaration functionDeclaration) {
302 visitInvokable(functionDeclaration); 303 visitInvokable(functionDeclaration);
303 } 304 }
304 } 305 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_model/closure.dart ('k') | pkg/compiler/lib/src/js_model/js_strategy.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698