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

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

Issue 3009903002: Pass in `this` as a free variable to the closure class (Closed)
Patch Set: . 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
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 // parameters, and type parameters are declared in the class, not 171 // parameters, and type parameters are declared in the class, not
172 // the factory. 172 // the factory.
173 _currentScopeInfo.freeVariables.add(variable); 173 _currentScopeInfo.freeVariables.add(variable);
174 } 174 }
175 if (_inTry) { 175 if (_inTry) {
176 _currentScopeInfo.localsUsedInTryOrSync.add(variable); 176 _currentScopeInfo.localsUsedInTryOrSync.add(variable);
177 } 177 }
178 } 178 }
179 179
180 @override 180 @override
181 void visitThisExpression(ir.ThisExpression thisExpression) {
182 if (_hasThisLocal) _registerNeedsThis();
183 }
184
185 @override
186 void visitTypeParameter(ir.TypeParameter typeParameter) {
187 ir.TreeNode context = _executableContext;
188 if (_isInsideClosure && context is ir.Procedure && context.isFactory) {
189 // This is a closure in a factory constructor. Since there is no
190 // [:this:], we have to mark the type arguments as free variables to
191 // capture them in the closure.
192 // TODO(efortuna): Implement for in the case of RTI.
193 // useTypeVariableAsLocal(typeParameter.bound);
194 }
195
196 if (_executableContext is ir.Member &&
197 _executableContext is! ir.Field &&
198 _hasThisLocal) {
199 // In checked mode, using a type variable in a type annotation may lead
200 // to a runtime type check that needs to access the type argument and
201 // therefore the closure needs a this-element, if it is not in a field
202 // initializer; field initializers are evaluated in a context where
203 // the type arguments are available in locals.
204 _registerNeedsThis();
205 }
206 }
207
208 /// Add `this` as a variable that needs to be accessed (and thus may become a
209 /// free/captured variable.
210 void _registerNeedsThis() {
211 if (_isInsideClosure) {
212 _currentScopeInfo.freeVariables.add(const ThisVariable());
Johnni Winther 2017/08/31 07:24:38 Add a `needsThis` property on [KernelScopeInfo] in
Emily Fortuna 2017/08/31 17:40:52 Done.
213 }
214 }
215
216 @override
181 void visitForStatement(ir.ForStatement node) { 217 void visitForStatement(ir.ForStatement node) {
182 List<ir.VariableDeclaration> boxedLoopVariables = 218 List<ir.VariableDeclaration> boxedLoopVariables =
183 <ir.VariableDeclaration>[]; 219 <ir.VariableDeclaration>[];
184 enterNewScope(node, () { 220 enterNewScope(node, () {
185 // First visit initialized variables and update steps so we can easily 221 // First visit initialized variables and update steps so we can easily
186 // check if a loop variable was captured in one of these subexpressions. 222 // check if a loop variable was captured in one of these subexpressions.
187 node.variables 223 node.variables
188 .forEach((ir.VariableDeclaration variable) => variable.accept(this)); 224 .forEach((ir.VariableDeclaration variable) => variable.accept(this));
189 node.updates 225 node.updates
190 .forEach((ir.Expression expression) => expression.accept(this)); 226 .forEach((ir.Expression expression) => expression.accept(this));
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 @override 332 @override
297 void visitFunctionExpression(ir.FunctionExpression functionExpression) { 333 void visitFunctionExpression(ir.FunctionExpression functionExpression) {
298 visitInvokable(functionExpression); 334 visitInvokable(functionExpression);
299 } 335 }
300 336
301 @override 337 @override
302 void visitFunctionDeclaration(ir.FunctionDeclaration functionDeclaration) { 338 void visitFunctionDeclaration(ir.FunctionDeclaration functionDeclaration) {
303 visitInvokable(functionDeclaration); 339 visitInvokable(functionDeclaration);
304 } 340 }
305 } 341 }
342
343 /// A fake sentinel "ir" node place holder representing the usage of `this`
344 /// inside closures that occur inside members.
345 class ThisVariable implements ir.VariableDeclaration {
346 const ThisVariable();
347
348 bool get isConst => true;
349 set isConst(bool constVal) =>
350 throw new UnsupportedError("ThisVariable.setIsConst");
351 bool get isFinal => true;
352 set isFinal(bool finalValue) =>
353 throw new UnsupportedError("ThisVariable.setIsFinal");
354 bool get isCovariant => false;
355 set isCovariant(bool covariant) =>
356 throw new UnsupportedError("ThisVariable.setIsCovariant");
357 bool get isFieldFormal => false;
358 set isFieldFormal(bool formal) =>
359 throw new UnsupportedError("ThisVariable.setIsFieldFormal");
360 String get name => 'this';
361 set name(String name) => throw new UnsupportedError("ThisVariable.setName");
362 set type(ir.DartType type) => throw new UnsupportedError("ThisVariable.type");
363 int get fileOffset => throw new UnsupportedError("ThisVariable.fileOffset");
364 set fileOffset(int offset) =>
365 throw new UnsupportedError("ThisVariable.setFileOffset");
366
367 int get binaryOffsetNoTag =>
368 throw new UnsupportedError("ThisVariable.binaryOffsetNoTag");
369 set binaryOffsetNoTag(int offset) =>
370 throw new UnsupportedError("ThisVariable.binaryOffsetNoTag");
371
372 int get fileEqualsOffset =>
373 throw new UnsupportedError("ThisVariable.fileEqualsOffset");
374 set fileEqualsOffset(int offset) =>
375 throw new UnsupportedError("ThisVariable.setFileEqualsOffset");
376
377 int get flags => throw new UnsupportedError("ThisVariable.flags");
378 set flags(int flags) => throw new UnsupportedError("ThisVariable.flags");
379
380 ir.DartType get type =>
381 throw new UnsupportedError("Sentinel this does not have a type.");
382
383 ir.TreeNode get parent =>
384 throw new UnsupportedError("Sentinel this does not have a parent.");
385
386 set parent(ir.TreeNode parent) =>
387 throw new UnsupportedError("Sentinel this does not have a parent.");
388
389 ir.Expression get initializer => null;
390 set initializer(ir.Expression expression) =>
391 throw new UnsupportedError("ThisVariable.setInitializer");
392
393 accept(ir.StatementVisitor v) => throw new UnsupportedError(
394 "ThisVariable should not be walked in AST traversal");
395 accept1(ir.StatementVisitor1 v, arg) => throw new UnsupportedError(
396 "ThisVariable should not be walked in AST traversal");
397
398 visitChildren(ir.Visitor v) {
399 throw new UnsupportedError(
400 "ThisVariable should not be walked in AST traversal");
401 }
402
403 transformChildren(ir.Transformer v) {
404 throw new UnsupportedError(
405 "ThisVariable should not be walked in AST traversal");
406 }
407
408 void replaceChild(ir.TreeNode child, ir.TreeNode replacement) =>
409 throw new UnsupportedError("ThisVariable.replaceChild");
410
411 void replaceWith(ir.TreeNode replacement) =>
412 throw new UnsupportedError("ThisVariable.replaceWith");
413
414 void remove() => throw new UnsupportedError("ThisVariable.remove");
415
416 ir.Program get enclosingProgram =>
417 throw new UnsupportedError("ThisVariable.enclosingProgram");
418
419 ir.Location get location =>
420 throw new UnsupportedError("ThisVariable.location");
421
422 String toString() => 'thisVariable';
423 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698