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

Unified Diff: pkg/compiler/lib/src/closure.dart

Issue 2936693002: Reapply "Separate out loop closure information." (Closed)
Patch Set: call with ast.node instead of ir.Node until we update that path. 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/closure.dart
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 4ba469bf367921d5fb77fbb528febca2c35561d6..6320e1f7bbaea75450fccf13e2594ab2825f031e 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -30,6 +30,10 @@ abstract class ClosureClassMaps<T> {
ClosureClassMap getMemberMap(MemberEntity member);
ClosureClassMap getLocalFunctionMap(Local localFunction);
+ /// Look up information about a loop, in case any variables it declares need
+ /// to be boxed/snapshotted.
+ LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(T loopNode);
+
/// Accessor to the information about closures that the SSA builder will use.
ClosureAnalysisInfo getClosureAnalysisInfo(T node);
}
@@ -50,12 +54,43 @@ class ClosureAnalysisInfo {
/// Accessor to the local environment in which a particular closure node is
/// executed. This will encapsulate the value of any variables that have been
/// scoped into this context from outside. This is an accessor to the
- /// contextBox that [requiresContextBox] is testing for.
+ /// contextBox that [requiresContextBox] is testing is required.
Local get context => null;
/// True if the specified variable has been mutated inside the scope of this
/// closure.
bool isCaptured(Local variable) => false;
+
+ /// Loop through every variable that has been captured in this closure. This
+ /// consists of all the free variables (variables captured *just* in this
+ /// closure) and all variables captured in nested scopes that we may be
+ /// capturing as well.
+ void forEachCapturedVariable(f(Local from, FieldEntity to)) {}
+}
+
+/// Class that describes the actual mechanics of how a loop is
+/// converted/rewritten without closures. Unlike JS, the value of a declared
+/// loop iteration variable in any closure is captured/snapshotted inside at
+/// each iteration point, as if we created a new local variable for that value
+/// inside the loop. For example, for the following loop:
+///
+/// var lst = [];
+/// for (int i = 0; i < 5; i++) lst.add(()=>i);
+///
+/// The result of `lst` will be [0, 1, 2, 3, 4], whereas were this JS code
+/// the result would be [5, 5, 5, 5, 5]. Because of this difference we need to
+/// create a closure for these sorts of loops to capture the variable's value at
+/// each iteration, by boxing the iteration variable[s].
+class LoopClosureRepresentationInfo extends ClosureAnalysisInfo {
+ const LoopClosureRepresentationInfo();
+
+ /// True if this loop declares any variables that need to be boxed.
+ bool get hasBoxedVariables => false;
+
+ /// The set of iteration variables (or variables declared in the for loop
+ /// expression (`for (...here...)`) that need to be boxed to snapshot their
+ /// value.
+ List<Local> get boxedVariables => const <Local>[];
}
class ClosureTask extends CompilerTask implements ClosureClassMaps<Node> {
@@ -76,6 +111,12 @@ class ClosureTask extends CompilerTask implements ClosureClassMaps<Node> {
return value == null ? const ClosureAnalysisInfo() : value;
}
+ LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(
+ Node loopNode) {
+ var value = _closureInfoMap[loopNode];
+ return value == null ? const LoopClosureRepresentationInfo() : value;
+ }
+
ClosureClassMap getMemberMap(MemberElement member) {
return getClosureToClassMapping(member);
}
@@ -445,7 +486,8 @@ class SynthesizedCallMethodElementX extends BaseFunctionElementX
// The box-element for a scope, and the captured variables that need to be
// stored in the box.
-class ClosureScope implements ClosureAnalysisInfo {
+class ClosureScope
+ implements ClosureAnalysisInfo, LoopClosureRepresentationInfo {
final BoxLocal boxElement;
final Map<Local, BoxFieldElement> capturedVariables;
@@ -462,7 +504,7 @@ class ClosureScope implements ClosureAnalysisInfo {
List<Local> get boxedVariables => boxedLoopVariables;
- bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty;
+ bool get hasBoxedVariables => !boxedLoopVariables.isEmpty;
bool isCaptured(Local variable) {
return capturedVariables.containsKey(variable);
@@ -552,6 +594,9 @@ class ClosureClassMap {
freeVariableMap.forEach(f);
}
+ bool isVariableUsedInTryOrSync(Local variable) =>
+ variablesUsedInTryOrGenerator.contains(variable);
+
Local getLocalVariableForClosureField(ClosureFieldElement field) {
return field.local;
}
« no previous file with comments | « no previous file | pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698