| Index: pkg/compiler/lib/src/closure.dart
|
| diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
|
| index 1315016223cc19d886833805cc1cb95159cde915..70ce85f6951943bf51789b7aef25d904ef9a6025 100644
|
| --- a/pkg/compiler/lib/src/closure.dart
|
| +++ b/pkg/compiler/lib/src/closure.dart
|
| @@ -5,31 +5,22 @@
|
| library closureToClassMapper;
|
|
|
| import 'common.dart';
|
| -import 'common/names.dart' show
|
| - Identifiers;
|
| -import 'common/resolution.dart' show
|
| - Parsing,
|
| - Resolution;
|
| -import 'common/tasks.dart' show
|
| - CompilerTask;
|
| -import 'compiler.dart' show
|
| - Compiler;
|
| +import 'common/names.dart' show Identifiers;
|
| +import 'common/resolution.dart' show Parsing, Resolution;
|
| +import 'common/tasks.dart' show CompilerTask;
|
| +import 'compiler.dart' show Compiler;
|
| import 'constants/expressions.dart';
|
| import 'dart_types.dart';
|
| import 'elements/elements.dart';
|
| -import 'elements/modelx.dart' show
|
| - BaseFunctionElementX,
|
| - ClassElementX,
|
| - ElementX,
|
| - LocalFunctionElementX;
|
| +import 'elements/modelx.dart'
|
| + show BaseFunctionElementX, ClassElementX, ElementX, LocalFunctionElementX;
|
| import 'elements/visitor.dart' show ElementVisitor;
|
| import 'js_backend/js_backend.dart' show JavaScriptBackend;
|
| import 'resolution/tree_elements.dart' show TreeElements;
|
| import 'tokens/token.dart' show Token;
|
| import 'tree/tree.dart';
|
| import 'util/util.dart';
|
| -import 'universe/universe.dart' show
|
| - Universe;
|
| +import 'universe/universe.dart' show Universe;
|
|
|
| class ClosureTask extends CompilerTask {
|
| Map<Node, ClosureClassMap> closureMappingCache;
|
| @@ -39,9 +30,8 @@ class ClosureTask extends CompilerTask {
|
|
|
| String get name => "Closure Simplifier";
|
|
|
| - ClosureClassMap computeClosureToClassMapping(Element element,
|
| - Node node,
|
| - TreeElements elements) {
|
| + ClosureClassMap computeClosureToClassMapping(
|
| + Element element, Node node, TreeElements elements) {
|
| return measure(() {
|
| ClosureClassMap cached = closureMappingCache[node];
|
| if (cached != null) return cached;
|
| @@ -107,9 +97,7 @@ class ClosureFieldElement extends ElementX
|
| /// The [BoxLocal] or [LocalElement] being accessed through the field.
|
| final Local local;
|
|
|
| - ClosureFieldElement(String name,
|
| - this.local,
|
| - ClosureClassElement enclosing)
|
| + ClosureFieldElement(String name, this.local, ClosureClassElement enclosing)
|
| : super(name, ElementKind.FIELD, enclosing);
|
|
|
| /// Use [closureClass] instead.
|
| @@ -128,8 +116,8 @@ class ClosureFieldElement extends ElementX
|
| bool get hasNode => false;
|
|
|
| Node get node {
|
| - throw new SpannableAssertionFailure(local,
|
| - 'Should not access node of ClosureFieldElement.');
|
| + throw new SpannableAssertionFailure(
|
| + local, 'Should not access node of ClosureFieldElement.');
|
| }
|
|
|
| bool get hasResolvedAst => hasTreeElements;
|
| @@ -139,8 +127,8 @@ class ClosureFieldElement extends ElementX
|
| }
|
|
|
| Expression get initializer {
|
| - throw new SpannableAssertionFailure(local,
|
| - 'Should not access initializer of ClosureFieldElement.');
|
| + throw new SpannableAssertionFailure(
|
| + local, 'Should not access initializer of ClosureFieldElement.');
|
| }
|
|
|
| bool get isInstanceMember => true;
|
| @@ -177,6 +165,7 @@ class ClosureClassElement extends ClassElementX {
|
| DartType rawType;
|
| DartType thisType;
|
| FunctionType callType;
|
| +
|
| /// Node that corresponds to this closure, used for source position.
|
| final FunctionExpression node;
|
|
|
| @@ -187,18 +176,17 @@ class ClosureClassElement extends ClassElementX {
|
|
|
| final List<ClosureFieldElement> _closureFields = <ClosureFieldElement>[];
|
|
|
| - ClosureClassElement(this.node,
|
| - String name,
|
| - Compiler compiler,
|
| - LocalFunctionElement closure)
|
| + ClosureClassElement(
|
| + this.node, String name, Compiler compiler, LocalFunctionElement closure)
|
| : this.methodElement = closure,
|
| - super(name,
|
| - closure.compilationUnit,
|
| - // By assigning a fresh class-id we make sure that the hashcode
|
| - // is unique, but also emit closure classes after all other
|
| - // classes (since the emitter sorts classes by their id).
|
| - compiler.getNextFreeClassId(),
|
| - STATE_DONE) {
|
| + super(
|
| + name,
|
| + closure.compilationUnit,
|
| + // By assigning a fresh class-id we make sure that the hashcode
|
| + // is unique, but also emit closure classes after all other
|
| + // classes (since the emitter sorts classes by their id).
|
| + compiler.getNextFreeClassId(),
|
| + STATE_DONE) {
|
| JavaScriptBackend backend = compiler.backend;
|
| ClassElement superclass = methodElement.isInstanceMember
|
| ? backend.helpers.boundClosureClass
|
| @@ -251,12 +239,14 @@ class BoxLocal extends Local {
|
| // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to
|
| // find a more general solution.
|
| class BoxFieldElement extends ElementX
|
| - implements TypedElement, CapturedVariable, FieldElement,
|
| + implements
|
| + TypedElement,
|
| + CapturedVariable,
|
| + FieldElement,
|
| PrivatelyNamedJSEntity {
|
| final BoxLocal box;
|
|
|
| - BoxFieldElement(String name, this.variableElement,
|
| - BoxLocal box)
|
| + BoxFieldElement(String name, this.variableElement, BoxLocal box)
|
| : this.box = box,
|
| super(name, ElementKind.FIELD, box.executableContext);
|
|
|
| @@ -323,9 +313,8 @@ class SynthesizedCallMethodElementX extends BaseFunctionElementX
|
| implements MethodElement {
|
| final LocalFunctionElement expression;
|
|
|
| - SynthesizedCallMethodElementX(String name,
|
| - LocalFunctionElementX other,
|
| - ClosureClassElement enclosing)
|
| + SynthesizedCallMethodElementX(
|
| + String name, LocalFunctionElementX other, ClosureClassElement enclosing)
|
| : expression = other,
|
| super(name, other.kind, other.modifiers, enclosing) {
|
| asyncMarker = other.asyncMarker;
|
| @@ -378,8 +367,8 @@ class ClosureScope {
|
| return capturedVariables.containsKey(variable);
|
| }
|
|
|
| - void forEachCapturedVariable(f(LocalVariableElement variable,
|
| - BoxFieldElement boxField)) {
|
| + void forEachCapturedVariable(
|
| + f(LocalVariableElement variable, BoxFieldElement boxField)) {
|
| capturedVariables.forEach(f);
|
| }
|
| }
|
| @@ -416,10 +405,8 @@ class ClosureClassMap {
|
| /// TODO(johnniwinter): Add variables to this only if the variable is mutated.
|
| final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>();
|
|
|
| - ClosureClassMap(this.closureElement,
|
| - this.closureClassElement,
|
| - this.callElement,
|
| - this.thisLocal);
|
| + ClosureClassMap(this.closureElement, this.closureClassElement,
|
| + this.callElement, this.thisLocal);
|
|
|
| void addFreeVariable(Local element) {
|
| assert(freeVariableMap[element] == null);
|
| @@ -432,8 +419,7 @@ class ClosureClassMap {
|
| return freeVariableMap.containsKey(element);
|
| }
|
|
|
| - void forEachFreeVariable(f(Local variable,
|
| - CapturedVariable field)) {
|
| + void forEachFreeVariable(f(Local variable, CapturedVariable field)) {
|
| freeVariableMap.forEach(f);
|
| }
|
|
|
| @@ -457,8 +443,7 @@ class ClosureClassMap {
|
| return capturingScopesBox(variable);
|
| }
|
|
|
| - void forEachCapturedVariable(void f(Local variable,
|
| - CapturedVariable field)) {
|
| + void forEachCapturedVariable(void f(Local variable, CapturedVariable field)) {
|
| freeVariableMap.forEach((variable, copy) {
|
| if (variable is BoxLocal) return;
|
| f(variable, copy);
|
| @@ -468,8 +453,8 @@ class ClosureClassMap {
|
| });
|
| }
|
|
|
| - void forEachBoxedVariable(void f(LocalVariableElement local,
|
| - BoxFieldElement field)) {
|
| + void forEachBoxedVariable(
|
| + void f(LocalVariableElement local, BoxFieldElement field)) {
|
| freeVariableMap.forEach((variable, copy) {
|
| if (!isVariableBoxed(variable)) return;
|
| f(variable, copy);
|
| @@ -521,9 +506,7 @@ class ClosureTranslator extends Visitor {
|
|
|
| bool insideClosure = false;
|
|
|
| - ClosureTranslator(this.compiler,
|
| - this.elements,
|
| - this.closureMappingCache);
|
| + ClosureTranslator(this.compiler, this.elements, this.closureMappingCache);
|
|
|
| DiagnosticReporter get reporter => compiler.reporter;
|
|
|
| @@ -568,8 +551,7 @@ class ClosureTranslator extends Visitor {
|
| _capturedVariableMapping[variable] = null;
|
| }
|
|
|
| - void setCapturedVariableBoxField(Local variable,
|
| - BoxFieldElement boxField) {
|
| + void setCapturedVariableBoxField(Local variable, BoxFieldElement boxField) {
|
| assert(isCapturedVariable(variable));
|
| _capturedVariableMapping[variable] = boxField;
|
| }
|
| @@ -591,9 +573,10 @@ class ClosureTranslator extends Visitor {
|
| }
|
|
|
| void translateLazyInitializer(VariableElement element,
|
| - VariableDefinitions node,
|
| - Expression initializer) {
|
| - visitInvokable(element, node, () { visit(initializer); });
|
| + VariableDefinitions node, Expression initializer) {
|
| + visitInvokable(element, node, () {
|
| + visit(initializer);
|
| + });
|
| updateClosures();
|
| }
|
|
|
| @@ -627,8 +610,7 @@ class ClosureTranslator extends Visitor {
|
| }
|
| });
|
| ClosureClassElement closureClass = data.closureClassElement;
|
| - assert(closureClass != null ||
|
| - (fieldCaptures.isEmpty && boxes.isEmpty));
|
| + assert(closureClass != null || (fieldCaptures.isEmpty && boxes.isEmpty));
|
|
|
| void addClosureField(Local local, String name) {
|
| ClosureFieldElement closureField =
|
| @@ -674,7 +656,7 @@ class ClosureTranslator extends Visitor {
|
| // the factory.
|
| bool inCurrentContext(Local variable) {
|
| return variable == executableContext ||
|
| - variable.executableContext == executableContext;
|
| + variable.executableContext == executableContext;
|
| }
|
|
|
| if (insideClosure && !inCurrentContext(variable)) {
|
| @@ -719,8 +701,8 @@ class ClosureTranslator extends Visitor {
|
| visit(node.type);
|
| }
|
| for (Link<Node> link = node.definitions.nodes;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| Node definition = link.head;
|
| LocalElement element = elements[definition];
|
| assert(element != null);
|
| @@ -748,7 +730,8 @@ class ClosureTranslator extends Visitor {
|
| // TODO(karlklose,johnniwinther): if the type is null, the annotation is
|
| // from a parameter which has been analyzed before the method has been
|
| // resolved and the result has been thrown away.
|
| - if (compiler.options.enableTypeAssertions && type != null &&
|
| + if (compiler.options.enableTypeAssertions &&
|
| + type != null &&
|
| type.containsTypeVariables) {
|
| if (insideClosure && member.isFactoryConstructor) {
|
| // This is a closure in a factory constructor. Since there is no
|
| @@ -775,8 +758,7 @@ class ClosureTranslator extends Visitor {
|
| } else {
|
| Element element = elements[node];
|
| if (element != null && element.isTypeVariable) {
|
| - if (outermostElement.isConstructor ||
|
| - outermostElement.isField) {
|
| + if (outermostElement.isConstructor || outermostElement.isField) {
|
| TypeVariableElement typeVariable = element;
|
| useTypeVariableAsLocal(typeVariable.type);
|
| } else {
|
| @@ -796,7 +778,7 @@ class ClosureTranslator extends Visitor {
|
| TypeVariableElement variable = element;
|
| analyzeType(variable.type);
|
| } else if (node.receiver == null &&
|
| - Elements.isInstanceSend(node, elements)) {
|
| + Elements.isInstanceSend(node, elements)) {
|
| registerNeedsThis();
|
| } else if (node.isSuperCall) {
|
| registerNeedsThis();
|
| @@ -848,8 +830,7 @@ class ClosureTranslator extends Visitor {
|
| type.forEachTypeVariable((TypeVariableType typeVariable) {
|
| // Field initializers are inlined and access the type variable as
|
| // normal parameters.
|
| - if (!outermostElement.isField &&
|
| - !outermostElement.isConstructor) {
|
| + if (!outermostElement.isField && !outermostElement.isConstructor) {
|
| registerNeedsThis();
|
| } else {
|
| useTypeVariableAsLocal(typeVariable);
|
| @@ -862,8 +843,7 @@ class ClosureTranslator extends Visitor {
|
| if (type == null) return;
|
| if (outermostElement.isClassMember &&
|
| compiler.backend.classNeedsRti(outermostElement.enclosingClass)) {
|
| - if (outermostElement.isConstructor ||
|
| - outermostElement.isField) {
|
| + if (outermostElement.isConstructor || outermostElement.isField) {
|
| analyzeTypeVariables(type);
|
| } else if (outermostElement.isInstanceMember) {
|
| if (type.containsTypeVariables) {
|
| @@ -958,8 +938,8 @@ class ClosureTranslator extends Visitor {
|
| node.initializer.asVariableDefinitions();
|
| if (definitions == null) return;
|
| for (Link<Node> link = definitions.definitions.nodes;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| Node definition = link.head;
|
| LocalVariableElement element = elements[definition];
|
| // Non-mutated variables should not be boxed. The mutatedVariables set
|
| @@ -984,20 +964,20 @@ class ClosureTranslator extends Visitor {
|
| parts = parts.prepend(ownName);
|
| }
|
| for (Element enclosingElement = element.enclosingElement;
|
| - enclosingElement != null &&
|
| - (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY
|
| - || enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR
|
| - || enclosingElement.kind == ElementKind.CLASS
|
| - || enclosingElement.kind == ElementKind.FUNCTION
|
| - || enclosingElement.kind == ElementKind.GETTER
|
| - || enclosingElement.kind == ElementKind.SETTER);
|
| - enclosingElement = enclosingElement.enclosingElement) {
|
| + enclosingElement != null &&
|
| + (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
|
| + enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR ||
|
| + enclosingElement.kind == ElementKind.CLASS ||
|
| + enclosingElement.kind == ElementKind.FUNCTION ||
|
| + enclosingElement.kind == ElementKind.GETTER ||
|
| + enclosingElement.kind == ElementKind.SETTER);
|
| + enclosingElement = enclosingElement.enclosingElement) {
|
| // TODO(johnniwinther): Simplify computed names.
|
| if (enclosingElement.isGenerativeConstructor ||
|
| enclosingElement.isGenerativeConstructorBody ||
|
| enclosingElement.isFactoryConstructor) {
|
| - parts = parts.prepend(
|
| - Elements.reconstructConstructorName(enclosingElement));
|
| + parts = parts
|
| + .prepend(Elements.reconstructConstructorName(enclosingElement));
|
| } else {
|
| String surroundingName =
|
| Elements.operatorNameToIdentifier(enclosingElement.name);
|
| @@ -1014,18 +994,16 @@ class ClosureTranslator extends Visitor {
|
|
|
| JavaScriptBackend get backend => compiler.backend;
|
|
|
| - ClosureClassMap globalizeClosure(FunctionExpression node,
|
| - LocalFunctionElement element) {
|
| + ClosureClassMap globalizeClosure(
|
| + FunctionExpression node, LocalFunctionElement element) {
|
| String closureName = computeClosureName(element);
|
| - ClosureClassElement globalizedElement = new ClosureClassElement(
|
| - node, closureName, compiler, element);
|
| + ClosureClassElement globalizedElement =
|
| + new ClosureClassElement(node, closureName, compiler, element);
|
| // Extend [globalizedElement] as an instantiated class in the closed world.
|
| - compiler.world.registerClass(
|
| - globalizedElement, isDirectlyInstantiated: true);
|
| - FunctionElement callElement =
|
| - new SynthesizedCallMethodElementX(Identifiers.call,
|
| - element,
|
| - globalizedElement);
|
| + compiler.world
|
| + .registerClass(globalizedElement, isDirectlyInstantiated: true);
|
| + FunctionElement callElement = new SynthesizedCallMethodElementX(
|
| + Identifiers.call, element, globalizedElement);
|
| backend.maybeMarkClosureAsNeededForReflection(
|
| globalizedElement, callElement, element);
|
| MemberElement enclosing = element.memberContext;
|
| @@ -1036,13 +1014,12 @@ class ClosureTranslator extends Visitor {
|
| // function. It could be [null] if we are inside a static method.
|
| ThisLocal thisElement = closureData.thisLocal;
|
|
|
| - return new ClosureClassMap(element, globalizedElement,
|
| - callElement, thisElement);
|
| + return new ClosureClassMap(
|
| + element, globalizedElement, callElement, thisElement);
|
| }
|
|
|
| - void visitInvokable(ExecutableElement element,
|
| - Node node,
|
| - void visitChildren()) {
|
| + void visitInvokable(
|
| + ExecutableElement element, Node node, void visitChildren()) {
|
| bool oldInsideClosure = insideClosure;
|
| Element oldFunctionElement = executableContext;
|
| ClosureClassMap oldClosureData = closureData;
|
| @@ -1070,14 +1047,13 @@ class ClosureTranslator extends Visitor {
|
| // escape the potential type variables used in that closure.
|
| if (element is FunctionElement &&
|
| (compiler.backend.methodNeedsRti(element) ||
|
| - compiler.options.enableTypeAssertions)) {
|
| + compiler.options.enableTypeAssertions)) {
|
| analyzeTypeVariables(type);
|
| }
|
|
|
| visitChildren();
|
| });
|
|
|
| -
|
| ClosureClassMap savedClosureData = closureData;
|
| bool savedInsideClosure = insideClosure;
|
|
|
|
|