Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: pkg/compiler/lib/src/closure.dart

Issue 2387353002: Eagerly compute closure classes (Closed)
Patch Set: Add comments. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/compiler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 'universe/world_builder.dart' show CodegenWorldBuilder; 22 import 'universe/world_builder.dart' show CodegenWorldBuilder;
23 import 'util/util.dart'; 23 import 'util/util.dart';
24 24
25 class ClosureTask extends CompilerTask { 25 class ClosureTask extends CompilerTask {
26 Map<Node, ClosureClassMap> closureMappingCache; 26 Map<Element, ClosureClassMap> _closureMappingCache =
27 <Element, ClosureClassMap>{};
27 Compiler compiler; 28 Compiler compiler;
28 ClosureTask(Compiler compiler) 29 ClosureTask(Compiler compiler)
29 : closureMappingCache = new Map<Node, ClosureClassMap>(), 30 : compiler = compiler,
30 compiler = compiler,
31 super(compiler.measurer); 31 super(compiler.measurer);
32 32
33 String get name => "Closure Simplifier"; 33 String get name => "Closure Simplifier";
34 34
35 DiagnosticReporter get reporter => compiler.reporter; 35 DiagnosticReporter get reporter => compiler.reporter;
36 36
37 /// Returns the [ClosureClassMap] computed for [resolvedAst].
38 ClosureClassMap getClosureToClassMapping(ResolvedAst resolvedAst) {
39 return measure(() {
40 Element element = resolvedAst.element;
41 if (element.isGenerativeConstructorBody) {
42 ConstructorBodyElement constructorBody = element;
43 element = constructorBody.constructor;
44 }
45 ClosureClassMap closureClassMap = _closureMappingCache[element];
46 assert(invariant(resolvedAst.element, closureClassMap != null,
47 message: "No ClosureClassMap computed for ${element}."));
48 return closureClassMap;
49 });
50 }
51
52 /// Create [ClosureClassMap]s for all live members.
53 void createClosureClasses() {
54 compiler.enqueuer.resolution.processedElements
55 .forEach((AstElement element) {
56 ResolvedAst resolvedAst = element.resolvedAst;
57 if (element.isAbstract) return;
58 if (element.isField &&
59 !element.isInstanceMember &&
60 resolvedAst.body == null) {
61 // Skip top-level/static fields without an initializer.
62 return;
63 }
64 computeClosureToClassMapping(resolvedAst);
65 });
66 }
67
37 ClosureClassMap computeClosureToClassMapping(ResolvedAst resolvedAst) { 68 ClosureClassMap computeClosureToClassMapping(ResolvedAst resolvedAst) {
38 return measure(() { 69 return measure(() {
39 Element element = resolvedAst.element; 70 Element element = resolvedAst.element;
71 ClosureClassMap cached = _closureMappingCache[element];
72 if (cached != null) return cached;
40 if (resolvedAst.kind != ResolvedAstKind.PARSED) { 73 if (resolvedAst.kind != ResolvedAstKind.PARSED) {
41 return new ClosureClassMap(null, null, null, new ThisLocal(element)); 74 return _closureMappingCache[element] =
75 new ClosureClassMap(null, null, null, new ThisLocal(element));
42 } 76 }
43 return reporter.withCurrentElement(element.implementation, () { 77 return reporter.withCurrentElement(element.implementation, () {
44 Node node = resolvedAst.node; 78 Node node = resolvedAst.node;
45 TreeElements elements = resolvedAst.elements; 79 TreeElements elements = resolvedAst.elements;
46 80
47 ClosureClassMap cached = closureMappingCache[node];
48 if (cached != null) return cached;
49
50 ClosureTranslator translator = 81 ClosureTranslator translator =
51 new ClosureTranslator(compiler, elements, closureMappingCache); 82 new ClosureTranslator(compiler, elements, _closureMappingCache);
52 83
53 // The translator will store the computed closure-mappings inside the 84 // The translator will store the computed closure-mappings inside the
54 // cache. One for given node and one for each nested closure. 85 // cache. One for given node and one for each nested closure.
55 if (node is FunctionExpression) { 86 if (node is FunctionExpression) {
56 translator.translateFunction(element, node); 87 translator.translateFunction(element, node);
57 } else if (element.isSynthesized) { 88 } else if (element.isSynthesized) {
58 reporter.internalError( 89 reporter.internalError(
59 element, "Unexpected synthesized element: $element"); 90 element, "Unexpected synthesized element: $element");
60 return new ClosureClassMap(null, null, null, new ThisLocal(element)); 91 _closureMappingCache[element] =
92 new ClosureClassMap(null, null, null, new ThisLocal(element));
61 } else { 93 } else {
62 assert(invariant(element, element.isField, 94 assert(invariant(element, element.isField,
63 message: "Expected $element to be a field.")); 95 message: "Expected $element to be a field."));
64 Node initializer = resolvedAst.body; 96 Node initializer = resolvedAst.body;
65 if (initializer != null) { 97 if (initializer != null) {
66 // The lazy initializer of a static. 98 // The lazy initializer of a static.
67 translator.translateLazyInitializer(element, node, initializer); 99 translator.translateLazyInitializer(element, node, initializer);
68 } else { 100 } else {
69 assert(invariant(element, element.isInstanceMember, 101 assert(invariant(element, element.isInstanceMember,
70 message: "Expected $element (${element 102 message: "Expected $element (${element
71 .runtimeType}) to be an instance field.")); 103 .runtimeType}) to be an instance field."));
72 closureMappingCache[node] = 104 _closureMappingCache[element] =
73 new ClosureClassMap(null, null, null, new ThisLocal(element)); 105 new ClosureClassMap(null, null, null, new ThisLocal(element));
74 } 106 }
75 } 107 }
76 assert(closureMappingCache[node] != null); 108 assert(invariant(element, _closureMappingCache[element] != null,
77 return closureMappingCache[node]; 109 message: "No ClosureClassMap computed for ${element}."));
110 return _closureMappingCache[element];
78 }); 111 });
79 }); 112 });
80 } 113 }
81 114
82 ClosureClassMap getMappingForNestedFunction(FunctionExpression node) {
83 return measure(() {
84 ClosureClassMap nestedClosureData = closureMappingCache[node];
85 if (nestedClosureData == null) {
86 reporter.internalError(node, "No closure cache.");
87 }
88 return nestedClosureData;
89 });
90 }
91
92 void forgetElement(var closure) { 115 void forgetElement(var closure) {
93 ClosureClassElement cls; 116 ClosureClassElement cls;
94 if (closure is ClosureFieldElement) { 117 if (closure is ClosureFieldElement) {
95 cls = closure.closureClass; 118 cls = closure.closureClass;
96 } else if (closure is SynthesizedCallMethodElementX) { 119 } else if (closure is SynthesizedCallMethodElementX) {
97 cls = closure.closureClass; 120 cls = closure.closureClass;
98 } else { 121 } else {
99 throw new SpannableAssertionFailure( 122 throw new SpannableAssertionFailure(
100 closure, 'Not a closure: $closure (${closure.runtimeType}).'); 123 closure, 'Not a closure: $closure (${closure.runtimeType}).');
101 } 124 }
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 } 542 }
520 } 543 }
521 544
522 class ClosureTranslator extends Visitor { 545 class ClosureTranslator extends Visitor {
523 final Compiler compiler; 546 final Compiler compiler;
524 final TreeElements elements; 547 final TreeElements elements;
525 int closureFieldCounter = 0; 548 int closureFieldCounter = 0;
526 int boxedFieldCounter = 0; 549 int boxedFieldCounter = 0;
527 bool inTryStatement = false; 550 bool inTryStatement = false;
528 551
529 final Map<Node, ClosureClassMap> closureMappingCache; 552 final Map<Element, ClosureClassMap> closureMappingCache;
530 553
531 // Map of captured variables. Initially they will map to `null`. If 554 // Map of captured variables. Initially they will map to `null`. If
532 // a variable needs to be boxed then the scope declaring the variable 555 // a variable needs to be boxed then the scope declaring the variable
533 // will update this to mapping to the capturing [BoxFieldElement]. 556 // will update this to mapping to the capturing [BoxFieldElement].
534 Map<Local, BoxFieldElement> _capturedVariableMapping = 557 Map<Local, BoxFieldElement> _capturedVariableMapping =
535 new Map<Local, BoxFieldElement>(); 558 new Map<Local, BoxFieldElement>();
536 559
537 // List of encountered closures. 560 // List of encountered closures.
538 List<Expression> closures = <Expression>[]; 561 List<LocalFunctionElement> closures = <LocalFunctionElement>[];
539 562
540 // The local variables that have been declared in the current scope. 563 // The local variables that have been declared in the current scope.
541 List<LocalVariableElement> scopeVariables; 564 List<LocalVariableElement> scopeVariables;
542 565
543 // Keep track of the mutated local variables so that we don't need to box 566 // Keep track of the mutated local variables so that we don't need to box
544 // non-mutated variables. 567 // non-mutated variables.
545 Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>(); 568 Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>();
546 569
547 MemberElement outermostElement; 570 MemberElement outermostElement;
548 ExecutableElement executableContext; 571 ExecutableElement executableContext;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 visitInvokable(element, node, () { 646 visitInvokable(element, node, () {
624 visit(initializer); 647 visit(initializer);
625 }); 648 });
626 updateClosures(); 649 updateClosures();
627 } 650 }
628 651
629 // This function runs through all of the existing closures and updates their 652 // This function runs through all of the existing closures and updates their
630 // free variables to the boxed value. It also adds the field-elements to the 653 // free variables to the boxed value. It also adds the field-elements to the
631 // class representing the closure. 654 // class representing the closure.
632 void updateClosures() { 655 void updateClosures() {
633 for (Expression closure in closures) { 656 for (LocalFunctionElement closure in closures) {
634 // The captured variables that need to be stored in a field of the closure 657 // The captured variables that need to be stored in a field of the closure
635 // class. 658 // class.
636 Set<Local> fieldCaptures = new Set<Local>(); 659 Set<Local> fieldCaptures = new Set<Local>();
637 Set<BoxLocal> boxes = new Set<BoxLocal>(); 660 Set<BoxLocal> boxes = new Set<BoxLocal>();
638 ClosureClassMap data = closureMappingCache[closure]; 661 ClosureClassMap data = closureMappingCache[closure];
639 // We get a copy of the keys and iterate over it, to avoid modifications 662 // We get a copy of the keys and iterate over it, to avoid modifications
640 // to the map while iterating over it. 663 // to the map while iterating over it.
641 Iterable<Local> freeVariables = data.freeVariables.toList(); 664 Iterable<Local> freeVariables = data.freeVariables.toList();
642 freeVariables.forEach((Local fromElement) { 665 freeVariables.forEach((Local fromElement) {
643 assert(data.isFreeVariable(fromElement)); 666 assert(data.isFreeVariable(fromElement));
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 ExecutableElement element, Node node, void visitChildren()) { 1090 ExecutableElement element, Node node, void visitChildren()) {
1068 bool oldInsideClosure = insideClosure; 1091 bool oldInsideClosure = insideClosure;
1069 Element oldFunctionElement = executableContext; 1092 Element oldFunctionElement = executableContext;
1070 ClosureClassMap oldClosureData = closureData; 1093 ClosureClassMap oldClosureData = closureData;
1071 1094
1072 insideClosure = outermostElement != null; 1095 insideClosure = outermostElement != null;
1073 LocalFunctionElement closure; 1096 LocalFunctionElement closure;
1074 executableContext = element; 1097 executableContext = element;
1075 if (insideClosure) { 1098 if (insideClosure) {
1076 closure = element; 1099 closure = element;
1077 closures.add(node); 1100 closures.add(closure);
1078 closureData = globalizeClosure(node, closure); 1101 closureData = globalizeClosure(node, closure);
1079 } else { 1102 } else {
1080 outermostElement = element; 1103 outermostElement = element;
1081 ThisLocal thisElement = null; 1104 ThisLocal thisElement = null;
1082 if (element.isInstanceMember || element.isGenerativeConstructor) { 1105 if (element.isInstanceMember || element.isGenerativeConstructor) {
1083 thisElement = new ThisLocal(element); 1106 thisElement = new ThisLocal(element);
1084 } 1107 }
1085 closureData = new ClosureClassMap(null, null, null, thisElement); 1108 closureData = new ClosureClassMap(null, null, null, thisElement);
1086 } 1109 }
1087 closureMappingCache[node] = closureData; 1110 closureMappingCache[element.declaration] = closureData;
1111 if (closureData.callElement != null) {
1112 closureMappingCache[closureData.callElement] = closureData;
1113 }
1088 1114
1089 inNewScope(node, () { 1115 inNewScope(node, () {
1090 DartType type = element.type; 1116 DartType type = element.type;
1091 // If the method needs RTI, or checked mode is set, we need to 1117 // If the method needs RTI, or checked mode is set, we need to
1092 // escape the potential type variables used in that closure. 1118 // escape the potential type variables used in that closure.
1093 if (element is FunctionElement && 1119 if (element is FunctionElement &&
1094 (compiler.backend.methodNeedsRti(element) || 1120 (compiler.backend.methodNeedsRti(element) ||
1095 compiler.options.enableTypeAssertions)) { 1121 compiler.options.enableTypeAssertions)) {
1096 analyzeTypeVariables(type); 1122 analyzeTypeVariables(type);
1097 } 1123 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1183 /// 1209 ///
1184 /// Move the below classes to a JS model eventually. 1210 /// Move the below classes to a JS model eventually.
1185 /// 1211 ///
1186 abstract class JSEntity implements Entity { 1212 abstract class JSEntity implements Entity {
1187 Entity get declaredEntity; 1213 Entity get declaredEntity;
1188 } 1214 }
1189 1215
1190 abstract class PrivatelyNamedJSEntity implements JSEntity { 1216 abstract class PrivatelyNamedJSEntity implements JSEntity {
1191 Entity get rootOfScope; 1217 Entity get rootOfScope;
1192 } 1218 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698