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

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

Issue 2992763002: Add boxed fields in closure classes. (Closed)
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
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
(...skipping 16 matching lines...) Expand all
27 /// about variable usage in the surrounding scope. 27 /// about variable usage in the surrounding scope.
28 Map<ir.FunctionNode, KernelScopeInfo> get _closuresToGenerate => 28 Map<ir.FunctionNode, KernelScopeInfo> get _closuresToGenerate =>
29 _model.closuresToGenerate; 29 _model.closuresToGenerate;
30 30
31 /// The local variables that have been declared in the current scope. 31 /// The local variables that have been declared in the current scope.
32 List<ir.VariableDeclaration> _scopeVariables; 32 List<ir.VariableDeclaration> _scopeVariables;
33 33
34 /// Pointer to the context in which this closure is executed. 34 /// Pointer to the context in which this closure is executed.
35 /// For example, in the expression `var foo = () => 3 + i;`, the executable 35 /// For example, in the expression `var foo = () => 3 + i;`, the executable
36 /// context as we walk the nodes in that expression is the ir.Field `foo`. 36 /// context as we walk the nodes in that expression is the ir.Field `foo`.
37 ir.Node _executableContext; 37 ir.TreeNode _executableContext;
38 38
39 /// A flag to indicate if we are currently inside a closure. 39 /// A flag to indicate if we are currently inside a closure.
40 bool _isInsideClosure = false; 40 bool _isInsideClosure = false;
41 41
42 /// Pointer to the original node where this closure builder started. 42 /// Pointer to the original node where this closure builder started.
43 ir.Node _outermostNode; 43 ir.Node _outermostNode;
44 44
45 /// Keep track of the mutated local variables so that we don't need to box 45 /// Keep track of the mutated local variables so that we don't need to box
46 /// non-mutated variables. 46 /// non-mutated variables.
47 Set<ir.VariableDeclaration> _mutatedVariables = 47 Set<ir.VariableDeclaration> _mutatedVariables =
48 new Set<ir.VariableDeclaration>(); 48 new Set<ir.VariableDeclaration>();
49 49
50 /// The set of variables that are accessed in some form, whether they are 50 /// The set of variables that are accessed in some form, whether they are
51 /// mutated or not. 51 /// mutated or not.
52 Set<ir.VariableDeclaration> _capturedVariables = 52 Set<ir.VariableDeclaration> _capturedVariables =
53 new Set<ir.VariableDeclaration>(); 53 new Set<ir.VariableDeclaration>();
54 54
55 /// If true, the visitor is currently traversing some nodes that are inside a 55 /// If true, the visitor is currently traversing some nodes that are inside a
56 /// try block. 56 /// try block.
57 bool _inTry = false; 57 bool _inTry = false;
58 58
59 /// The current scope we are in. 59 /// The current scope we are in.
60 KernelScopeInfo _currentScopeInfo; 60 KernelScopeInfo _currentScopeInfo;
61 61
62 final bool _hasThisLocal; 62 final bool _hasThisLocal;
63 63
64 /// Keeps track of the number of boxes that we've created so that they each
65 /// have unique names.
66 int _boxCounter = 0;
67
64 CapturedScopeBuilder(this._model, {bool hasThisLocal}) 68 CapturedScopeBuilder(this._model, {bool hasThisLocal})
65 : this._hasThisLocal = hasThisLocal; 69 : this._hasThisLocal = hasThisLocal;
66 70
67 /// Update the [CapturedScope] object corresponding to 71 /// Update the [CapturedScope] object corresponding to
68 /// this node if any variables are captured. 72 /// this node if any variables are captured.
69 void attachCapturedScopeVariables(ir.Node node) { 73 void attachCapturedScopeVariables(ir.Node node) {
70 Set<ir.VariableDeclaration> capturedVariablesForScope = 74 Set<ir.VariableDeclaration> capturedVariablesForScope =
71 new Set<ir.VariableDeclaration>(); 75 new Set<ir.VariableDeclaration>();
72 76
73 for (ir.VariableDeclaration variable in _scopeVariables) { 77 for (ir.VariableDeclaration variable in _scopeVariables) {
74 // No need to box non-assignable elements. 78 // No need to box non-assignable elements.
75 if (variable.isFinal || variable.isConst) continue; 79 if (variable.isFinal || variable.isConst) continue;
76 if (!_mutatedVariables.contains(variable)) continue; 80 if (!_mutatedVariables.contains(variable)) continue;
77 if (_capturedVariables.contains(variable)) { 81 if (_capturedVariables.contains(variable)) {
78 capturedVariablesForScope.add(variable); 82 capturedVariablesForScope.add(variable);
79 } 83 }
80 } 84 }
81 if (!capturedVariablesForScope.isEmpty) { 85 if (!capturedVariablesForScope.isEmpty) {
82 assert(_model.scopeInfo != null); 86 assert(_model.scopeInfo != null);
83 assert(_currentLocalFunction != null); 87 assert(_currentLocalFunction != null);
84 KernelScopeInfo from = _model.scopeInfo; 88 KernelScopeInfo from = _model.scopeInfo;
85 _scopesCapturedInClosureMap[node] = new KernelCapturedScope( 89 _scopesCapturedInClosureMap[node] = new KernelCapturedScope(
86 capturedVariablesForScope, 90 capturedVariablesForScope,
91 new NodeBox(getBoxName(), _executableContext,
92 _getMemberContext(_executableContext)),
Johnni Winther 2017/08/01 09:09:10 The member context is not needed. See comment in [
Emily Fortuna 2017/08/01 19:30:06 got it.
87 _currentLocalFunction, 93 _currentLocalFunction,
88 from.localsUsedInTryOrSync, 94 from.localsUsedInTryOrSync,
89 from.freeVariables, 95 from.freeVariables,
90 _hasThisLocal); 96 _hasThisLocal);
91 } 97 }
92 } 98 }
93 99
100 /// Look up the outermost member that contains this node.
101 ///
102 /// For top level, static or instance members, the member context is the
103 /// node itself. For parameters, local variables and nested closures, the
104 /// member context is the top level, static or instance member in which it is
105 /// defined.
106 ir.Member _getMemberContext(ir.TreeNode startNode) {
107 ir.TreeNode node = startNode;
108 while (node is! ir.Member && node != _outermostNode) {
109 node = node.parent;
110 }
111 assert(node is ir.Member);
112 return node;
113 }
114
115 /// Generate a unique name for the [_boxCounter]th box field.
116 ///
117 /// The result is used as the name of [NodeBox]s and [BoxLocal]s, and must
118 /// therefore be unique to avoid breaking an invariant in the element model
119 /// (classes cannot declare multiple fields with the same name).
120 ///
121 /// Also, the names should be distinct from real field names to prevent
122 /// clashes with selectors for those fields.
123 ///
124 /// These names are not used in generated code, just as element name.
125 String getBoxName() {
126 return "_box_${_boxCounter++}";
127 }
128
94 /// Perform book-keeping with the current set of local variables that have 129 /// Perform book-keeping with the current set of local variables that have
95 /// been seen thus far before entering this new scope. 130 /// been seen thus far before entering this new scope.
96 void enterNewScope(ir.Node node, void visitNewScope()) { 131 void enterNewScope(ir.Node node, void visitNewScope()) {
97 List<ir.VariableDeclaration> oldScopeVariables = _scopeVariables; 132 List<ir.VariableDeclaration> oldScopeVariables = _scopeVariables;
98 _scopeVariables = <ir.VariableDeclaration>[]; 133 _scopeVariables = <ir.VariableDeclaration>[];
99 visitNewScope(); 134 visitNewScope();
100 attachCapturedScopeVariables(node); 135 attachCapturedScopeVariables(node);
101 _mutatedVariables.removeAll(_scopeVariables); 136 _mutatedVariables.removeAll(_scopeVariables);
102 _scopeVariables = oldScopeVariables; 137 _scopeVariables = oldScopeVariables;
103 } 138 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 if (_capturedVariables.contains(variable) && 220 if (_capturedVariables.contains(variable) &&
186 _mutatedVariables.contains(variable)) { 221 _mutatedVariables.contains(variable)) {
187 boxedLoopVariables.add(variable); 222 boxedLoopVariables.add(variable);
188 } 223 }
189 } 224 }
190 }); 225 });
191 KernelCapturedScope scope = _scopesCapturedInClosureMap[node]; 226 KernelCapturedScope scope = _scopesCapturedInClosureMap[node];
192 if (scope == null) return; 227 if (scope == null) return;
193 _scopesCapturedInClosureMap[node] = new KernelCapturedLoopScope( 228 _scopesCapturedInClosureMap[node] = new KernelCapturedLoopScope(
194 scope.boxedVariables, 229 scope.boxedVariables,
230 scope.capturedVariablesAccessor,
195 boxedLoopVariables, 231 boxedLoopVariables,
196 scope.context, 232 scope.context,
197 scope.localsUsedInTryOrSync, 233 scope.localsUsedInTryOrSync,
198 scope.freeVariables, 234 scope.freeVariables,
199 scope.hasThisLocal); 235 scope.hasThisLocal);
200 } 236 }
201 237
202 void visitInvokable(ir.TreeNode node) { 238 void visitInvokable(ir.TreeNode node) {
203 bool oldIsInsideClosure = _isInsideClosure; 239 bool oldIsInsideClosure = _isInsideClosure;
204 ir.Node oldExecutableContext = _executableContext; 240 ir.TreeNode oldExecutableContext = _executableContext;
205 KernelScopeInfo oldScopeInfo = _currentScopeInfo; 241 KernelScopeInfo oldScopeInfo = _currentScopeInfo;
206 ir.TreeNode oldLocalFunction = _currentLocalFunction; 242 ir.TreeNode oldLocalFunction = _currentLocalFunction;
207 243
208 // _outermostNode is only null the first time we enter the body of the 244 // _outermostNode is only null the first time we enter the body of the
209 // field, constructor, or method that is being analyzed. 245 // field, constructor, or method that is being analyzed.
210 _isInsideClosure = _outermostNode != null; 246 _isInsideClosure = _outermostNode != null;
211 _executableContext = node; 247 _executableContext = node;
212 248
213 _currentScopeInfo = new KernelScopeInfo(_hasThisLocal); 249 _currentScopeInfo = new KernelScopeInfo(_hasThisLocal);
214 if (_isInsideClosure) { 250 if (_isInsideClosure) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 } 294 }
259 295
260 void translateConstructorOrProcedure(ir.Node constructorOrProcedure) { 296 void translateConstructorOrProcedure(ir.Node constructorOrProcedure) {
261 constructorOrProcedure.accept(this); 297 constructorOrProcedure.accept(this);
262 } 298 }
263 299
264 void visitFunctionNode(ir.FunctionNode functionNode) { 300 void visitFunctionNode(ir.FunctionNode functionNode) {
265 visitInvokable(functionNode); 301 visitInvokable(functionNode);
266 } 302 }
267 } 303 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698