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

Unified Diff: pkg/kernel/lib/transformations/closure/info.dart

Issue 2939043002: Remove unnecessary contexts in closure conversion (Closed)
Patch Set: Add helper function, add example to the comment Created 3 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: pkg/kernel/lib/transformations/closure/info.dart
diff --git a/pkg/kernel/lib/transformations/closure/info.dart b/pkg/kernel/lib/transformations/closure/info.dart
index 2d9c2ca3c90f6f38ea3b78201741b63a3eaa7c94..7b9bd32454da6cd87d71f4ef96753839367e0fb4 100644
--- a/pkg/kernel/lib/transformations/closure/info.dart
+++ b/pkg/kernel/lib/transformations/closure/info.dart
@@ -9,13 +9,17 @@ import '../../ast.dart'
Class,
Constructor,
Field,
+ FieldInitializer,
FunctionDeclaration,
FunctionNode,
+ LocalInitializer,
Member,
Name,
Procedure,
ProcedureKind,
PropertyGet,
+ RedirectingInitializer,
+ SuperInitializer,
ThisExpression,
TypeParameter,
TypeParameterType,
@@ -100,8 +104,31 @@ class ClosureInfo extends RecursiveVisitor {
}
visitConstructor(Constructor node) {
+ // For constructors we need to set [currentFunction] before visiting the
+ // [FunctionNode] of the constructor, because initializers may use
+ // constructor parameters and it shouldn't be treated as capturing them.
+ // Consider the following code:
+ //
+ // class A {
+ // int x;
+ // A(int x) /* "x" is visible in initializers and body. */
Dmitry Stefantsov 2017/06/16 08:36:27 I think I missed a spot here. "x" should have bee
karlklose 2017/06/16 08:43:40 Consider using '///' and '[x]' here and below (alt
Dmitry Stefantsov 2017/06/16 08:55:28 Done.
+ // : this.x = x { /* Initializer. */
+ // /* Constructor body. */
+ // }
+ // }
+ //
+ // Here _x_ parameter shouldn't be captured into a context in the
karlklose 2017/06/16 08:43:41 "_x_ parameter" -> "the parameter"?
Dmitry Stefantsov 2017/06/16 08:55:27 Done.
+ // initializer. However, if [currentFunction] is not set, it has _null_
karlklose 2017/06/16 08:43:41 How about 'However, [currentFunction] is `null` if
Dmitry Stefantsov 2017/06/16 08:55:28 Agree, that reads much better.
+ // value, and _function[node.variable]_ in this case points to the
+ // [FunctionNode] of the constructor (which is not _null_). It leads to "x"
karlklose 2017/06/16 08:43:41 `null`
Dmitry Stefantsov 2017/06/16 08:55:28 Done.
+ // being treated as captured, because it's seen as used outside of the
+ // function where it is declared. In turn, it leads to unnecessary context
+ // creation and usage.
beginMember(node, node.function);
- super.visitConstructor(node);
+ saveCurrentFunction(() {
+ currentFunction = currentMemberFunction;
+ super.visitConstructor(node);
+ });
endMember();
}
@@ -158,10 +185,12 @@ class ClosureInfo extends RecursiveVisitor {
visitFunctionNode(FunctionNode node) {
localNames.putIfAbsent(node, computeUniqueLocalName);
- var saved = currentFunction;
- currentFunction = node;
- node.visitChildren(this);
- currentFunction = saved;
+
+ saveCurrentFunction(() {
+ currentFunction = node;
+ node.visitChildren(this);
+ });
+
Set<TypeParameter> capturedTypeVariables = typeVariables[node];
if (capturedTypeVariables != null && !isOuterMostContext) {
// Propagate captured type variables to enclosing function.
@@ -209,4 +238,13 @@ class ClosureInfo extends RecursiveVisitor {
invokedGetters.add(node.name);
super.visitPropertyGet(node);
}
+
+ saveCurrentFunction(void f()) {
+ var saved = currentFunction;
+ try {
+ f();
+ } finally {
+ currentFunction = saved;
+ }
+ }
}

Powered by Google App Engine
This is Rietveld 408576698