| Index: pkg/compiler/lib/src/closure.dart
|
| diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
|
| index f9d431729deac978f979396b763357b61e1d1d67..e0c6826227443fe27a6bbcaa5f2f4558067b7e4f 100644
|
| --- a/pkg/compiler/lib/src/closure.dart
|
| +++ b/pkg/compiler/lib/src/closure.dart
|
| @@ -23,32 +23,63 @@ import 'universe/world_builder.dart' show CodegenWorldBuilder;
|
| import 'util/util.dart';
|
|
|
| class ClosureTask extends CompilerTask {
|
| - Map<Node, ClosureClassMap> closureMappingCache;
|
| + Map<Element, ClosureClassMap> _closureMappingCache =
|
| + <Element, ClosureClassMap>{};
|
| Compiler compiler;
|
| ClosureTask(Compiler compiler)
|
| - : closureMappingCache = new Map<Node, ClosureClassMap>(),
|
| - compiler = compiler,
|
| + : compiler = compiler,
|
| super(compiler.measurer);
|
|
|
| String get name => "Closure Simplifier";
|
|
|
| DiagnosticReporter get reporter => compiler.reporter;
|
|
|
| + /// Returns the [ClosureClassMap] computed for [resolvedAst].
|
| + ClosureClassMap getClosureToClassMapping(ResolvedAst resolvedAst) {
|
| + return measure(() {
|
| + Element element = resolvedAst.element;
|
| + if (element.isGenerativeConstructorBody) {
|
| + ConstructorBodyElement constructorBody = element;
|
| + element = constructorBody.constructor;
|
| + }
|
| + ClosureClassMap closureClassMap = _closureMappingCache[element];
|
| + assert(invariant(resolvedAst.element, closureClassMap != null,
|
| + message: "No ClosureClassMap computed for ${element}."));
|
| + return closureClassMap;
|
| + });
|
| + }
|
| +
|
| + /// Create [ClosureClassMap]s for all live members.
|
| + void createClosureClasses() {
|
| + compiler.enqueuer.resolution.processedElements
|
| + .forEach((AstElement element) {
|
| + ResolvedAst resolvedAst = element.resolvedAst;
|
| + if (element.isAbstract) return;
|
| + if (element.isField &&
|
| + !element.isInstanceMember &&
|
| + resolvedAst.body == null) {
|
| + // Skip top-level/static fields without an initializer.
|
| + return;
|
| + }
|
| + computeClosureToClassMapping(resolvedAst);
|
| + });
|
| + }
|
| +
|
| ClosureClassMap computeClosureToClassMapping(ResolvedAst resolvedAst) {
|
| return measure(() {
|
| Element element = resolvedAst.element;
|
| + ClosureClassMap cached = _closureMappingCache[element];
|
| + if (cached != null) return cached;
|
| if (resolvedAst.kind != ResolvedAstKind.PARSED) {
|
| - return new ClosureClassMap(null, null, null, new ThisLocal(element));
|
| + return _closureMappingCache[element] =
|
| + new ClosureClassMap(null, null, null, new ThisLocal(element));
|
| }
|
| return reporter.withCurrentElement(element.implementation, () {
|
| Node node = resolvedAst.node;
|
| TreeElements elements = resolvedAst.elements;
|
|
|
| - ClosureClassMap cached = closureMappingCache[node];
|
| - if (cached != null) return cached;
|
| -
|
| ClosureTranslator translator =
|
| - new ClosureTranslator(compiler, elements, closureMappingCache);
|
| + new ClosureTranslator(compiler, elements, _closureMappingCache);
|
|
|
| // The translator will store the computed closure-mappings inside the
|
| // cache. One for given node and one for each nested closure.
|
| @@ -57,7 +88,8 @@ class ClosureTask extends CompilerTask {
|
| } else if (element.isSynthesized) {
|
| reporter.internalError(
|
| element, "Unexpected synthesized element: $element");
|
| - return new ClosureClassMap(null, null, null, new ThisLocal(element));
|
| + _closureMappingCache[element] =
|
| + new ClosureClassMap(null, null, null, new ThisLocal(element));
|
| } else {
|
| assert(invariant(element, element.isField,
|
| message: "Expected $element to be a field."));
|
| @@ -69,26 +101,17 @@ class ClosureTask extends CompilerTask {
|
| assert(invariant(element, element.isInstanceMember,
|
| message: "Expected $element (${element
|
| .runtimeType}) to be an instance field."));
|
| - closureMappingCache[node] =
|
| + _closureMappingCache[element] =
|
| new ClosureClassMap(null, null, null, new ThisLocal(element));
|
| }
|
| }
|
| - assert(closureMappingCache[node] != null);
|
| - return closureMappingCache[node];
|
| + assert(invariant(element, _closureMappingCache[element] != null,
|
| + message: "No ClosureClassMap computed for ${element}."));
|
| + return _closureMappingCache[element];
|
| });
|
| });
|
| }
|
|
|
| - ClosureClassMap getMappingForNestedFunction(FunctionExpression node) {
|
| - return measure(() {
|
| - ClosureClassMap nestedClosureData = closureMappingCache[node];
|
| - if (nestedClosureData == null) {
|
| - reporter.internalError(node, "No closure cache.");
|
| - }
|
| - return nestedClosureData;
|
| - });
|
| - }
|
| -
|
| void forgetElement(var closure) {
|
| ClosureClassElement cls;
|
| if (closure is ClosureFieldElement) {
|
| @@ -526,7 +549,7 @@ class ClosureTranslator extends Visitor {
|
| int boxedFieldCounter = 0;
|
| bool inTryStatement = false;
|
|
|
| - final Map<Node, ClosureClassMap> closureMappingCache;
|
| + final Map<Element, ClosureClassMap> closureMappingCache;
|
|
|
| // Map of captured variables. Initially they will map to `null`. If
|
| // a variable needs to be boxed then the scope declaring the variable
|
| @@ -535,7 +558,7 @@ class ClosureTranslator extends Visitor {
|
| new Map<Local, BoxFieldElement>();
|
|
|
| // List of encountered closures.
|
| - List<Expression> closures = <Expression>[];
|
| + List<LocalFunctionElement> closures = <LocalFunctionElement>[];
|
|
|
| // The local variables that have been declared in the current scope.
|
| List<LocalVariableElement> scopeVariables;
|
| @@ -630,7 +653,7 @@ class ClosureTranslator extends Visitor {
|
| // free variables to the boxed value. It also adds the field-elements to the
|
| // class representing the closure.
|
| void updateClosures() {
|
| - for (Expression closure in closures) {
|
| + for (LocalFunctionElement closure in closures) {
|
| // The captured variables that need to be stored in a field of the closure
|
| // class.
|
| Set<Local> fieldCaptures = new Set<Local>();
|
| @@ -1074,7 +1097,7 @@ class ClosureTranslator extends Visitor {
|
| executableContext = element;
|
| if (insideClosure) {
|
| closure = element;
|
| - closures.add(node);
|
| + closures.add(closure);
|
| closureData = globalizeClosure(node, closure);
|
| } else {
|
| outermostElement = element;
|
| @@ -1084,7 +1107,10 @@ class ClosureTranslator extends Visitor {
|
| }
|
| closureData = new ClosureClassMap(null, null, null, thisElement);
|
| }
|
| - closureMappingCache[node] = closureData;
|
| + closureMappingCache[element.declaration] = closureData;
|
| + if (closureData.callElement != null) {
|
| + closureMappingCache[closureData.callElement] = closureData;
|
| + }
|
|
|
| inNewScope(node, () {
|
| DartType type = element.type;
|
|
|