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 |