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

Side by Side Diff: pkg/kernel/lib/transformations/closure/info.dart

Issue 2991853002: Fix duplicate context creation when closures appear in initializers. (Closed)
Patch Set: Review comments. 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) 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 library kernel.transformations.closure.info; 5 library kernel.transformations.closure.info;
6 6
7 import '../../ast.dart' 7 import '../../ast.dart'
8 show 8 show
9 Class, 9 Class,
10 Constructor, 10 Constructor,
11 Field, 11 Field,
12 FunctionDeclaration, 12 FunctionDeclaration,
13 FunctionNode, 13 FunctionNode,
14 Member, 14 Member,
15 Procedure, 15 Procedure,
16 ThisExpression, 16 ThisExpression,
17 TypeParameter, 17 TypeParameter,
18 TypeParameterType, 18 TypeParameterType,
19 VariableDeclaration, 19 VariableDeclaration,
20 VariableGet, 20 VariableGet,
21 VariableSet, 21 VariableSet,
22 visitList; 22 visitList;
23 23
24 import '../../visitor.dart' show RecursiveVisitor; 24 import '../../visitor.dart' show RecursiveVisitor;
25 25
26 class ClosureInfo extends RecursiveVisitor { 26 class ClosureInfo extends RecursiveVisitor {
27 FunctionNode currentFunction; 27 FunctionNode currentFunction;
28
29 static const int OUTSIDE_INITIALIZER = 1;
30 static const int INSIDE_INITIALIZER = 2;
31
32 int captureFlags = OUTSIDE_INITIALIZER;
33
34 // For function parameters, we need to distinquish the following states:
35 //
36 // - captured inside initializers, not used in body (INSIDE_INITIALIZER)
37 // - only used in body (OUTSIDE_INITIALIZER)
38 // - captured inside initializers and used in body (OUTSIDE_INITIALIZER |
39 // INSIDE_INITIALIZER)
40 //
Dmitry Stefantsov 2017/08/01 09:36:14 Please, remove the empty comment line here.
sjindel 2017/08/01 14:58:25 Done.
41 final Map<VariableDeclaration, int> variables = <VariableDeclaration, int>{};
Dmitry Stefantsov 2017/08/01 09:36:14 How about adding helper functions to hide the inte
sjindel 2017/08/01 14:58:25 I would prefer the second approach over the first,
Dmitry Stefantsov 2017/08/03 09:28:26 I guess it depends on the definition of "significa
42
28 final Map<VariableDeclaration, FunctionNode> function = 43 final Map<VariableDeclaration, FunctionNode> function =
29 <VariableDeclaration, FunctionNode>{}; 44 <VariableDeclaration, FunctionNode>{};
30 45
31 final Set<VariableDeclaration> variables = new Set<VariableDeclaration>();
32
33 /// Map from functions to set of type variables captured within them. 46 /// Map from functions to set of type variables captured within them.
34 final Map<FunctionNode, Set<TypeParameter>> typeVariables = 47 final Map<FunctionNode, Set<TypeParameter>> typeVariables =
35 <FunctionNode, Set<TypeParameter>>{}; 48 <FunctionNode, Set<TypeParameter>>{};
36 49
37 /// Map from members to synthetic variables for accessing `this` in a local 50 /// Map from members to synthetic variables for accessing `this` in a local
38 /// function. 51 /// function.
39 final Map<FunctionNode, VariableDeclaration> thisAccess = 52 final Map<FunctionNode, VariableDeclaration> thisAccess =
40 <FunctionNode, VariableDeclaration>{}; 53 <FunctionNode, VariableDeclaration>{};
41 54
42 final Set<String> currentMemberLocalNames = new Set<String>(); 55 final Set<String> currentMemberLocalNames = new Set<String>();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 /// the parameters that may be used in the initializers. If the nodes are 113 /// the parameters that may be used in the initializers. If the nodes are
101 /// visited in another order, the encountered parameters in initializers 114 /// visited in another order, the encountered parameters in initializers
102 /// are treated as captured, because they are not yet associated with the 115 /// are treated as captured, because they are not yet associated with the
103 /// function. 116 /// function.
104 beginMember(node, node.function); 117 beginMember(node, node.function);
105 saveCurrentFunction(() { 118 saveCurrentFunction(() {
106 currentFunction = currentMemberFunction; 119 currentFunction = currentMemberFunction;
107 120
108 visitList(node.annotations, this); 121 visitList(node.annotations, this);
109 node.name?.accept(this); 122 node.name?.accept(this);
110 node.function?.accept(this); 123
124 visitList(node.function.typeParameters, this);
125 visitList(node.function.positionalParameters, this);
126 visitList(node.function.namedParameters, this);
127
128 assert(captureFlags == OUTSIDE_INITIALIZER);
129 captureFlags = INSIDE_INITIALIZER;
111 visitList(node.initializers, this); 130 visitList(node.initializers, this);
131 captureFlags = OUTSIDE_INITIALIZER;
132
133 node.function.accept(this);
112 }); 134 });
113 endMember(); 135 endMember();
114 } 136 }
115 137
116 visitProcedure(Procedure node) { 138 visitProcedure(Procedure node) {
117 beginMember(node, node.function); 139 beginMember(node, node.function);
118 super.visitProcedure(node); 140 super.visitProcedure(node);
119 endMember(); 141 endMember();
120 } 142 }
121 143
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 } 196 }
175 } 197 }
176 198
177 visitVariableDeclaration(VariableDeclaration node) { 199 visitVariableDeclaration(VariableDeclaration node) {
178 function[node] = currentFunction; 200 function[node] = currentFunction;
179 node.visitChildren(this); 201 node.visitChildren(this);
180 } 202 }
181 203
182 visitVariableGet(VariableGet node) { 204 visitVariableGet(VariableGet node) {
183 if (function[node.variable] != currentFunction) { 205 if (function[node.variable] != currentFunction) {
184 variables.add(node.variable); 206 variables.putIfAbsent(node.variable, () => 0);
207 }
208 if (variables.containsKey(node.variable)) {
209 variables[node.variable] |= captureFlags;
185 } 210 }
186 node.visitChildren(this); 211 node.visitChildren(this);
187 } 212 }
188 213
189 visitVariableSet(VariableSet node) { 214 visitVariableSet(VariableSet node) {
190 if (function[node.variable] != currentFunction) { 215 if (function[node.variable] != currentFunction) {
191 variables.add(node.variable); 216 variables.putIfAbsent(node.variable, () => 0);
217 }
218 if (variables.containsKey(node.variable)) {
219 variables[node.variable] |= captureFlags;
192 } 220 }
193 node.visitChildren(this); 221 node.visitChildren(this);
194 } 222 }
195 223
196 visitTypeParameterType(TypeParameterType node) { 224 visitTypeParameterType(TypeParameterType node) {
197 if (!isOuterMostContext && node.parameter.parent != currentFunction) { 225 if (!isOuterMostContext && node.parameter.parent != currentFunction) {
198 typeVariables 226 typeVariables
199 .putIfAbsent(currentFunction, () => new Set<TypeParameter>()) 227 .putIfAbsent(currentFunction, () => new Set<TypeParameter>())
200 .add(node.parameter); 228 .add(node.parameter);
201 } 229 }
202 } 230 }
203 231
204 visitThisExpression(ThisExpression node) { 232 visitThisExpression(ThisExpression node) {
205 if (!isOuterMostContext) { 233 if (!isOuterMostContext) {
206 thisAccess.putIfAbsent( 234 thisAccess.putIfAbsent(
207 currentMemberFunction, () => new VariableDeclaration("#self")); 235 currentMemberFunction, () => new VariableDeclaration("#self"));
208 } 236 }
209 } 237 }
210 238
211 saveCurrentFunction(void f()) { 239 saveCurrentFunction(void f()) {
212 var saved = currentFunction; 240 var saved = currentFunction;
213 try { 241 try {
214 f(); 242 f();
215 } finally { 243 } finally {
216 currentFunction = saved; 244 currentFunction = saved;
217 } 245 }
218 } 246 }
219 } 247 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698