Chromium Code Reviews| Index: lib/compiler/implementation/closure.dart |
| diff --git a/lib/compiler/implementation/ssa/closure.dart b/lib/compiler/implementation/closure.dart |
| similarity index 87% |
| rename from lib/compiler/implementation/ssa/closure.dart |
| rename to lib/compiler/implementation/closure.dart |
| index a3a11d4d82876c06db24cf9d84ad49b488e1de5e..17508c1e823e79eebfaaa53540438fc085fe66e8 100644 |
| --- a/lib/compiler/implementation/ssa/closure.dart |
| +++ b/lib/compiler/implementation/closure.dart |
| @@ -2,6 +2,48 @@ |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| +#library("closureToClassMapper"); |
|
ahe
2012/08/14 12:54:38
I like an empty line between #library and #import.
floitsch
2012/08/14 14:16:32
Done.
|
| +#import("elements/elements.dart"); |
| +#import("leg.dart"); |
| +#import("scanner/scannerlib.dart"); |
| +#import("tree/tree.dart"); |
| +#import("util/util.dart"); |
| + |
| +class ClosureTask extends CompilerTask { |
| + Map<Node, ClosureToClassMapping> closureMappingCache; |
| + ClosureTask(Compiler compiler) |
| + : closureMappingCache = new Map<Node, ClosureToClassMapping>(), |
| + super(compiler); |
| + |
| + String get name() => "Closure Simplifier"; |
| + |
| + ClosureToClassMapping computeClosureToClassMapping(FunctionExpression node, |
| + TreeElements elements) { |
| + return measure(() { |
| + ClosureToClassMapping cached = closureMappingCache[node]; |
| + if (cached !== null) return cached; |
| + |
| + ClosureTranslator translator = |
| + new ClosureTranslator(compiler, elements, closureMappingCache); |
| + // The translator will store the computed closure-mappings inside the |
| + // cache. One for given method and one for each nested closure. |
| + translator.translate(node); |
| + assert(closureMappingCache[node] != null); |
| + return closureMappingCache[node]; |
| + }); |
| + } |
| + |
| + ClosureToClassMapping getMappingForNestedFunction(FunctionExpression node) { |
|
ahe
2012/08/14 12:54:38
Should this be wrapped in measure?
floitsch
2012/08/14 14:16:32
It is just looking up in a hashmap, so the cost sh
|
| + ClosureToClassMapping nestedClosureData = closureMappingCache[node]; |
| + if (nestedClosureData === null) { |
| + // TODO(floitsch): we can only assume that the reason for not having a |
| + // closure data here is, because the function is inside an initializer. |
| + compiler.unimplemented("Closures inside initializers", node: node); |
| + } |
| + return nestedClosureData; |
| + } |
| +} |
| + |
| class ClosureFieldElement extends Element { |
| ClosureFieldElement(SourceString name, ClassElement enclosing) |
| : super(name, ElementKind.FIELD, enclosing); |
| @@ -64,7 +106,7 @@ class ClosureScope { |
| bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty(); |
| } |
| -class ClosureData { |
| +class ClosureToClassMapping { |
|
ahe
2012/08/14 12:54:38
If you don't like this name, consider "ClosureClas
floitsch
2012/08/14 14:16:32
As you can see I was struggling with the name. Hap
|
| // The closure's element before any translation. Will be null for methods. |
| final FunctionElement closureElement; |
| // The closureClassElement will be null for methods that are not local |
| @@ -94,7 +136,7 @@ class ClosureData { |
| final Set<Element> usedVariablesInTry; |
| - ClosureData(this.closureElement, |
| + ClosureToClassMapping(this.closureElement, |
| this.closureClassElement, |
| this.callElement, |
| this.thisElement) |
| @@ -107,11 +149,11 @@ class ClosureData { |
| } |
| class ClosureTranslator extends AbstractVisitor { |
| - final SsaBuilder builder; |
| + final Compiler compiler; |
| final TreeElements elements; |
| int closureFieldCounter = 0; |
| bool inTryStatement = false; |
| - final Map<Node, ClosureData> closureDataCache; |
| + final Map<Node, ClosureToClassMapping> closureMappingCache; |
| // Map of captured variables. Initially they will map to themselves. If |
| // a variable needs to be boxed then the scope declaring the variable |
| @@ -129,34 +171,22 @@ class ClosureTranslator extends AbstractVisitor { |
| FunctionElement currentFunctionElement; |
| // The closureData of the currentFunctionElement. |
| - ClosureData closureData; |
| + ClosureToClassMapping closureData; |
| bool insideClosure = false; |
| - Compiler get compiler() => builder.compiler; |
| - |
| - ClosureTranslator(SsaBuilder builder) |
| - : this.builder = builder, |
| - this.elements = builder.elements, |
| - capturedVariableMapping = new Map<Element, Element>(), |
| + ClosureTranslator(this.compiler, this.elements, this.closureMappingCache) |
| + : capturedVariableMapping = new Map<Element, Element>(), |
| closures = <FunctionExpression>[], |
| - mutatedVariables = new Set<Element>(), |
| - this.closureDataCache = builder.builder.closureDataCache; |
| - |
| - ClosureData translate(Node node) { |
| - // Closures have already been analyzed when visiting the surrounding |
| - // method/function. This also shortcuts for bailout functions. |
| - ClosureData cached = closureDataCache[node]; |
| - if (cached !== null) return cached; |
| + mutatedVariables = new Set<Element>(); |
| + void translate(Node node) { |
| visit(node); |
| // When variables need to be boxed their [capturedVariableMapping] is |
| // updated, but we delay updating the similar freeVariableMapping in the |
| // closure datas that capture these variables. |
| // The closures don't have their fields (in the closure class) set, either. |
| updateClosures(); |
| - |
| - return closureDataCache[node]; |
| } |
| // This function runs through all of the existing closures and updates their |
| @@ -168,7 +198,7 @@ class ClosureTranslator extends AbstractVisitor { |
| // The captured variables that need to be stored in a field of the closure |
| // class. |
| Set<Element> fieldCaptures = new Set<Element>(); |
| - ClosureData data = closureDataCache[closure]; |
| + ClosureToClassMapping data = closureMappingCache[closure]; |
| Map<Element, Element> freeVariableMapping = data.freeVariableMapping; |
| // We get a copy of the keys and iterate over it, to avoid modifications |
| // to the map while iterating over it. |
| @@ -363,7 +393,7 @@ class ClosureTranslator extends AbstractVisitor { |
| scopeData.boxedLoopVariables = result; |
| } |
| - ClosureData globalizeClosure(FunctionExpression node, Element element) { |
| + ClosureToClassMapping globalizeClosure(FunctionExpression node, Element element) { |
|
ahe
2012/08/14 12:54:38
Long line.
floitsch
2012/08/14 14:16:32
not anymore after the renaming.
|
| SourceString closureName = |
| new SourceString(compiler.namer.closureName(element)); |
| ClassElement globalizedElement = new ClosureClassElement( |
| @@ -377,7 +407,7 @@ class ClosureTranslator extends AbstractVisitor { |
| // The nested function's 'this' is the same as the one for the outer |
| // function. It could be [null] if we are inside a static method. |
| Element thisElement = closureData.thisElement; |
| - return new ClosureData(element, globalizedElement, |
| + return new ClosureToClassMapping(element, globalizedElement, |
| callElement, thisElement); |
|
ahe
2012/08/14 12:54:38
Indentation.
floitsch
2012/08/14 14:16:32
Done.
|
| } |
| @@ -394,7 +424,7 @@ class ClosureTranslator extends AbstractVisitor { |
| bool oldInsideClosure = insideClosure; |
| FunctionElement oldFunctionElement = currentFunctionElement; |
| - ClosureData oldClosureData = closureData; |
| + ClosureToClassMapping oldClosureData = closureData; |
| insideClosure = isClosure; |
| currentFunctionElement = elements[node]; |
| @@ -416,7 +446,7 @@ class ClosureTranslator extends AbstractVisitor { |
| } |
| thisElement = new ThisElement(thisEnclosingElement); |
| } |
| - closureData = new ClosureData(null, null, null, thisElement); |
| + closureData = new ClosureToClassMapping(null, null, null, thisElement); |
| } |
| inNewScope(node, () { |
| @@ -441,9 +471,9 @@ class ClosureTranslator extends AbstractVisitor { |
| if (node.body !== null) node.body.accept(this); |
| }); |
| - closureDataCache[node] = closureData; |
| + closureMappingCache[node] = closureData; |
| - ClosureData savedClosureData = closureData; |
| + ClosureToClassMapping savedClosureData = closureData; |
| bool savedInsideClosure = insideClosure; |
| // Restore old values. |