| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library closureToClassMapper; | 5 library closureToClassMapper; |
| 6 | 6 |
| 7 import 'common/names.dart' show Identifiers; | 7 import 'common/names.dart' show Identifiers; |
| 8 import 'common/resolution.dart' show ParsingContext, Resolution; | 8 import 'common/resolution.dart' show ParsingContext, Resolution; |
| 9 import 'common/tasks.dart' show CompilerTask; | 9 import 'common/tasks.dart' show CompilerTask; |
| 10 import 'common.dart'; | 10 import 'common.dart'; |
| 11 import 'compiler.dart' show Compiler; | 11 import 'compiler.dart' show Compiler; |
| 12 import 'constants/expressions.dart'; | 12 import 'constants/expressions.dart'; |
| 13 import 'dart_types.dart'; | 13 import 'dart_types.dart'; |
| 14 import 'elements/elements.dart'; | 14 import 'elements/elements.dart'; |
| 15 import 'elements/modelx.dart' | 15 import 'elements/modelx.dart' |
| 16 show BaseFunctionElementX, ClassElementX, ElementX; | 16 show BaseFunctionElementX, ClassElementX, ElementX; |
| 17 import 'elements/visitor.dart' show ElementVisitor; | 17 import 'elements/visitor.dart' show ElementVisitor; |
| 18 import 'js_backend/js_backend.dart' show JavaScriptBackend; | 18 import 'js_backend/js_backend.dart' show JavaScriptBackend; |
| 19 import 'resolution/tree_elements.dart' show TreeElements; | 19 import 'resolution/tree_elements.dart' show TreeElements; |
| 20 import 'tokens/token.dart' show Token; | 20 import 'tokens/token.dart' show Token; |
| 21 import 'tree/tree.dart'; | 21 import 'tree/tree.dart'; |
| 22 import 'util/util.dart'; | 22 import 'util/util.dart'; |
| 23 import 'world.dart' show ClosedWorldRefiner; |
| 23 | 24 |
| 24 class ClosureTask extends CompilerTask { | 25 class ClosureTask extends CompilerTask { |
| 25 Map<Element, ClosureClassMap> _closureMappingCache = | 26 Map<Element, ClosureClassMap> _closureMappingCache = |
| 26 <Element, ClosureClassMap>{}; | 27 <Element, ClosureClassMap>{}; |
| 27 Compiler compiler; | 28 Compiler compiler; |
| 28 ClosureTask(Compiler compiler) | 29 ClosureTask(Compiler compiler) |
| 29 : compiler = compiler, | 30 : compiler = compiler, |
| 30 super(compiler.measurer); | 31 super(compiler.measurer); |
| 31 | 32 |
| 32 String get name => "Closure Simplifier"; | 33 String get name => "Closure Simplifier"; |
| 33 | 34 |
| 34 DiagnosticReporter get reporter => compiler.reporter; | 35 DiagnosticReporter get reporter => compiler.reporter; |
| 35 | 36 |
| 36 /// Returns the [ClosureClassMap] computed for [resolvedAst]. | 37 /// Returns the [ClosureClassMap] computed for [resolvedAst]. |
| 37 ClosureClassMap getClosureToClassMapping(ResolvedAst resolvedAst) { | 38 ClosureClassMap getClosureToClassMapping(ResolvedAst resolvedAst) { |
| 38 return measure(() { | 39 return measure(() { |
| 39 Element element = resolvedAst.element; | 40 Element element = resolvedAst.element; |
| 40 if (element.isGenerativeConstructorBody) { | 41 if (element.isGenerativeConstructorBody) { |
| 41 ConstructorBodyElement constructorBody = element; | 42 ConstructorBodyElement constructorBody = element; |
| 42 element = constructorBody.constructor; | 43 element = constructorBody.constructor; |
| 43 } | 44 } |
| 44 ClosureClassMap closureClassMap = _closureMappingCache[element]; | 45 ClosureClassMap closureClassMap = _closureMappingCache[element]; |
| 45 assert(invariant(resolvedAst.element, closureClassMap != null, | 46 assert(invariant(resolvedAst.element, closureClassMap != null, |
| 46 message: "No ClosureClassMap computed for ${element}.")); | 47 message: "No ClosureClassMap computed for ${element}.")); |
| 47 return closureClassMap; | 48 return closureClassMap; |
| 48 }); | 49 }); |
| 49 } | 50 } |
| 50 | 51 |
| 51 /// Create [ClosureClassMap]s for all live members. | 52 /// Create [ClosureClassMap]s for all live members. |
| 52 void createClosureClasses() { | 53 void createClosureClasses(ClosedWorldRefiner closedWorldRefiner) { |
| 53 compiler.enqueuer.resolution.processedEntities | 54 compiler.enqueuer.resolution.processedEntities |
| 54 .forEach((AstElement element) { | 55 .forEach((AstElement element) { |
| 55 // TODO(johnniwinther): Typedefs should never be in processedElements. | 56 // TODO(johnniwinther): Typedefs should never be in processedElements. |
| 56 if (element.isTypedef) return; | 57 if (element.isTypedef) return; |
| 57 ResolvedAst resolvedAst = element.resolvedAst; | 58 ResolvedAst resolvedAst = element.resolvedAst; |
| 58 if (element.isAbstract) return; | 59 if (element.isAbstract) return; |
| 59 if (element.isField && | 60 if (element.isField && |
| 60 !element.isInstanceMember && | 61 !element.isInstanceMember && |
| 61 resolvedAst.body == null) { | 62 resolvedAst.body == null) { |
| 62 // Skip top-level/static fields without an initializer. | 63 // Skip top-level/static fields without an initializer. |
| 63 return; | 64 return; |
| 64 } | 65 } |
| 65 computeClosureToClassMapping(resolvedAst); | 66 computeClosureToClassMapping(resolvedAst, closedWorldRefiner); |
| 66 }); | 67 }); |
| 67 } | 68 } |
| 68 | 69 |
| 69 ClosureClassMap computeClosureToClassMapping(ResolvedAst resolvedAst) { | 70 ClosureClassMap computeClosureToClassMapping( |
| 71 ResolvedAst resolvedAst, ClosedWorldRefiner closedWorldRefiner) { |
| 70 return measure(() { | 72 return measure(() { |
| 71 Element element = resolvedAst.element; | 73 Element element = resolvedAst.element; |
| 72 ClosureClassMap cached = _closureMappingCache[element]; | 74 ClosureClassMap cached = _closureMappingCache[element]; |
| 73 if (cached != null) return cached; | 75 if (cached != null) return cached; |
| 74 if (resolvedAst.kind != ResolvedAstKind.PARSED) { | 76 if (resolvedAst.kind != ResolvedAstKind.PARSED) { |
| 75 return _closureMappingCache[element] = | 77 return _closureMappingCache[element] = |
| 76 new ClosureClassMap(null, null, null, new ThisLocal(element)); | 78 new ClosureClassMap(null, null, null, new ThisLocal(element)); |
| 77 } | 79 } |
| 78 return reporter.withCurrentElement(element.implementation, () { | 80 return reporter.withCurrentElement(element.implementation, () { |
| 79 Node node = resolvedAst.node; | 81 Node node = resolvedAst.node; |
| 80 TreeElements elements = resolvedAst.elements; | 82 TreeElements elements = resolvedAst.elements; |
| 81 | 83 |
| 82 ClosureTranslator translator = | 84 ClosureTranslator translator = new ClosureTranslator( |
| 83 new ClosureTranslator(compiler, elements, _closureMappingCache); | 85 compiler, closedWorldRefiner, elements, _closureMappingCache); |
| 84 | 86 |
| 85 // The translator will store the computed closure-mappings inside the | 87 // The translator will store the computed closure-mappings inside the |
| 86 // cache. One for given node and one for each nested closure. | 88 // cache. One for given node and one for each nested closure. |
| 87 if (node is FunctionExpression) { | 89 if (node is FunctionExpression) { |
| 88 translator.translateFunction(element, node); | 90 translator.translateFunction(element, node); |
| 89 } else if (element.isSynthesized) { | 91 } else if (element.isSynthesized) { |
| 90 reporter.internalError( | 92 reporter.internalError( |
| 91 element, "Unexpected synthesized element: $element"); | 93 element, "Unexpected synthesized element: $element"); |
| 92 _closureMappingCache[element] = | 94 _closureMappingCache[element] = |
| 93 new ClosureClassMap(null, null, null, new ThisLocal(element)); | 95 new ClosureClassMap(null, null, null, new ThisLocal(element)); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 f(variable, copy); | 540 f(variable, copy); |
| 539 }); | 541 }); |
| 540 capturingScopes.values.forEach((ClosureScope scope) { | 542 capturingScopes.values.forEach((ClosureScope scope) { |
| 541 scope.forEachCapturedVariable(f); | 543 scope.forEachCapturedVariable(f); |
| 542 }); | 544 }); |
| 543 } | 545 } |
| 544 } | 546 } |
| 545 | 547 |
| 546 class ClosureTranslator extends Visitor { | 548 class ClosureTranslator extends Visitor { |
| 547 final Compiler compiler; | 549 final Compiler compiler; |
| 550 final ClosedWorldRefiner closedWorldRefiner; |
| 548 final TreeElements elements; | 551 final TreeElements elements; |
| 549 int closureFieldCounter = 0; | 552 int closureFieldCounter = 0; |
| 550 int boxedFieldCounter = 0; | 553 int boxedFieldCounter = 0; |
| 551 bool inTryStatement = false; | 554 bool inTryStatement = false; |
| 552 | 555 |
| 553 final Map<Element, ClosureClassMap> closureMappingCache; | 556 final Map<Element, ClosureClassMap> closureMappingCache; |
| 554 | 557 |
| 555 // Map of captured variables. Initially they will map to `null`. If | 558 // Map of captured variables. Initially they will map to `null`. If |
| 556 // a variable needs to be boxed then the scope declaring the variable | 559 // a variable needs to be boxed then the scope declaring the variable |
| 557 // will update this to mapping to the capturing [BoxFieldElement]. | 560 // will update this to mapping to the capturing [BoxFieldElement]. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 569 Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>(); | 572 Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>(); |
| 570 | 573 |
| 571 MemberElement outermostElement; | 574 MemberElement outermostElement; |
| 572 ExecutableElement executableContext; | 575 ExecutableElement executableContext; |
| 573 | 576 |
| 574 // The closureData of the currentFunctionElement. | 577 // The closureData of the currentFunctionElement. |
| 575 ClosureClassMap closureData; | 578 ClosureClassMap closureData; |
| 576 | 579 |
| 577 bool insideClosure = false; | 580 bool insideClosure = false; |
| 578 | 581 |
| 579 ClosureTranslator(this.compiler, this.elements, this.closureMappingCache); | 582 ClosureTranslator(this.compiler, this.closedWorldRefiner, this.elements, |
| 583 this.closureMappingCache); |
| 580 | 584 |
| 581 DiagnosticReporter get reporter => compiler.reporter; | 585 DiagnosticReporter get reporter => compiler.reporter; |
| 582 | 586 |
| 583 /// Generate a unique name for the [id]th closure field, with proposed name | 587 /// Generate a unique name for the [id]th closure field, with proposed name |
| 584 /// [name]. | 588 /// [name]. |
| 585 /// | 589 /// |
| 586 /// The result is used as the name of [ClosureFieldElement]s, and must | 590 /// The result is used as the name of [ClosureFieldElement]s, and must |
| 587 /// therefore be unique to avoid breaking an invariant in the element model | 591 /// therefore be unique to avoid breaking an invariant in the element model |
| 588 /// (classes cannot declare multiple fields with the same name). | 592 /// (classes cannot declare multiple fields with the same name). |
| 589 /// | 593 /// |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1063 } | 1067 } |
| 1064 | 1068 |
| 1065 JavaScriptBackend get backend => compiler.backend; | 1069 JavaScriptBackend get backend => compiler.backend; |
| 1066 | 1070 |
| 1067 ClosureClassMap globalizeClosure( | 1071 ClosureClassMap globalizeClosure( |
| 1068 FunctionExpression node, LocalFunctionElement element) { | 1072 FunctionExpression node, LocalFunctionElement element) { |
| 1069 String closureName = computeClosureName(element); | 1073 String closureName = computeClosureName(element); |
| 1070 ClosureClassElement globalizedElement = | 1074 ClosureClassElement globalizedElement = |
| 1071 new ClosureClassElement(node, closureName, compiler, element); | 1075 new ClosureClassElement(node, closureName, compiler, element); |
| 1072 // Extend [globalizedElement] as an instantiated class in the closed world. | 1076 // Extend [globalizedElement] as an instantiated class in the closed world. |
| 1073 compiler.inferenceWorld.registerClosureClass(globalizedElement); | 1077 closedWorldRefiner.registerClosureClass(globalizedElement); |
| 1074 FunctionElement callElement = new SynthesizedCallMethodElementX( | 1078 FunctionElement callElement = new SynthesizedCallMethodElementX( |
| 1075 Identifiers.call, element, globalizedElement, node, elements); | 1079 Identifiers.call, element, globalizedElement, node, elements); |
| 1076 backend.maybeMarkClosureAsNeededForReflection( | 1080 backend.maybeMarkClosureAsNeededForReflection( |
| 1077 globalizedElement, callElement, element); | 1081 globalizedElement, callElement, element); |
| 1078 MemberElement enclosing = element.memberContext; | 1082 MemberElement enclosing = element.memberContext; |
| 1079 enclosing.nestedClosures.add(callElement); | 1083 enclosing.nestedClosures.add(callElement); |
| 1080 globalizedElement.addMember(callElement, reporter); | 1084 globalizedElement.addMember(callElement, reporter); |
| 1081 globalizedElement.computeAllClassMembers(compiler.resolution); | 1085 globalizedElement.computeAllClassMembers(compiler.resolution); |
| 1082 // The nested function's 'this' is the same as the one for the outer | 1086 // The nested function's 'this' is the same as the one for the outer |
| 1083 // function. It could be [null] if we are inside a static method. | 1087 // function. It could be [null] if we are inside a static method. |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1210 /// | 1214 /// |
| 1211 /// Move the below classes to a JS model eventually. | 1215 /// Move the below classes to a JS model eventually. |
| 1212 /// | 1216 /// |
| 1213 abstract class JSEntity implements Entity { | 1217 abstract class JSEntity implements Entity { |
| 1214 Entity get declaredEntity; | 1218 Entity get declaredEntity; |
| 1215 } | 1219 } |
| 1216 | 1220 |
| 1217 abstract class PrivatelyNamedJSEntity implements JSEntity { | 1221 abstract class PrivatelyNamedJSEntity implements JSEntity { |
| 1218 Entity get rootOfScope; | 1222 Entity get rootOfScope; |
| 1219 } | 1223 } |
| OLD | NEW |