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

Side by Side Diff: dart/sdk/lib/_internal/compiler/implementation/deferred_load.dart

Issue 12525007: Record dependency information to implement first version of dependency (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 deferred_load; 5 library deferred_load;
6 6
7 import 'dart:uri'; 7 import 'dart:uri';
8 import 'dart:collection';
8 9
9 import 'dart2jslib.dart' 10 import 'dart2jslib.dart'
10 show Compiler, 11 show Compiler,
11 CompilerTask, 12 CompilerTask,
12 ConstructedConstant, 13 ConstructedConstant,
13 MessageKind, 14 MessageKind,
14 SourceString, 15 SourceString,
15 StringConstant; 16 StringConstant;
16 17
17 import 'elements/elements.dart' 18 import 'elements/elements.dart'
18 show ClassElement, 19 show ClassElement,
19 Element, 20 Element,
21 Elements,
22 FunctionElement,
20 LibraryElement, 23 LibraryElement,
21 MetadataAnnotation; 24 MetadataAnnotation,
25 ScopeContainerElement;
22 26
23 import 'util/util.dart' 27 import 'util/util.dart'
24 show Link; 28 show Link;
25 29
26 import 'tree/tree.dart' 30 import 'tree/tree.dart'
27 show LibraryTag; 31 show LibraryTag,
32 Node,
33 Visitor;
34
35 import 'resolution/resolution.dart'
36 show TreeElements;
28 37
29 class DeferredLoadTask extends CompilerTask { 38 class DeferredLoadTask extends CompilerTask {
30 final Set<LibraryElement> deferredLibraries = new Set<LibraryElement>(); 39 final Set<LibraryElement> deferredLibraries = new Set<LibraryElement>();
40 final Set<Element> deferredElements = new LinkedHashSet<Element>();
kasperl 2013/03/06 10:26:51 Is there a reason this needs to be linked when the
ahe 2013/03/06 16:01:41 Done.
31 41
32 ClassElement cachedDeferredLibraryClass; 42 ClassElement cachedDeferredLibraryClass;
33 43
34 DeferredLoadTask(Compiler compiler) : super(compiler); 44 DeferredLoadTask(Compiler compiler) : super(compiler);
35 45
36 String get name => 'Lazy'; 46 String get name => 'Lazy';
kasperl 2013/03/06 10:26:51 Deferred?
ahe 2013/03/06 16:01:41 Done.
37 47
38 /// DeferredLibrary from dart:async 48 /// DeferredLibrary from dart:async
39 ClassElement get deferredLibraryClass { 49 ClassElement get deferredLibraryClass {
40 if (cachedDeferredLibraryClass == null) { 50 if (cachedDeferredLibraryClass == null) {
41 cachedDeferredLibraryClass = findDeferredLibraryClass(); 51 cachedDeferredLibraryClass = findDeferredLibraryClass();
42 } 52 }
43 return cachedDeferredLibraryClass; 53 return cachedDeferredLibraryClass;
44 } 54 }
45 55
46 ClassElement findDeferredLibraryClass() { 56 ClassElement findDeferredLibraryClass() {
47 var uri = new Uri.fromComponents(scheme: 'dart', path: 'async'); 57 var uri = new Uri.fromComponents(scheme: 'dart', path: 'async');
48 LibraryElement asyncLibrary = 58 LibraryElement asyncLibrary =
49 compiler.libraryLoader.loadLibrary(uri, null, uri); 59 compiler.libraryLoader.loadLibrary(uri, null, uri);
50 var element = asyncLibrary.find(const SourceString('DeferredLibrary')); 60 var element = asyncLibrary.find(const SourceString('DeferredLibrary'));
51 if (element == null) { 61 if (element == null) {
52 compiler.internalErrorOnElement( 62 compiler.internalErrorOnElement(
53 asyncLibrary, 63 asyncLibrary,
54 'dart:async library does not contain required class: ' 64 'dart:async library does not contain required class: '
55 'DeferredLibrary'); 65 'DeferredLibrary');
56 } 66 }
57 return element; 67 return element;
58 } 68 }
59 69
60 bool isDeferred(Element element) { 70 bool isDeferred(Element element) {
61 // TODO(ahe): This is really a graph coloring problem. We should 71 element = element.implementation;
62 // make sure that libraries and elements only used by a deferred 72 return deferredElements.contains(element);
63 // library are also deferred. 73 }
64 // Also, if something is deferred depends on your 74
65 // perspective. Inside a deferred library, other elements of the 75 bool isExplicitlyDeferred(Element element) {
66 // same library are not deferred. We should add an extra parameter 76 element = element.implementation;
67 // to this method to indicate "from where".
68 return deferredLibraries.contains(element.getLibrary()); 77 return deferredLibraries.contains(element.getLibrary());
69 } 78 }
70 79
71 void registerMainApp(LibraryElement mainApp) { 80 void onResolutionComplete(FunctionElement main) {
72 if (mainApp == null) return; 81 if (main == null) return;
82 LibraryElement mainApp = main.getLibrary();
73 measureElement(mainApp, () { 83 measureElement(mainApp, () {
74 deferredLibraries.addAll(findDeferredLibraries(mainApp)); 84 deferredLibraries.addAll(findDeferredLibraries(mainApp));
85 if (deferredLibraries.isEmpty) return;
86
87 Map<LibraryElement, Set<Element>> deferredElements =
kasperl 2013/03/06 10:26:51 Not sure the shadowing (field/local) here helps th
ahe 2013/03/06 16:01:41 Done.
88 new LinkedHashMap<LibraryElement, Set<Element>>();
89 Set<Element> eagerElements = new LinkedHashSet<Element>();
90
91 mainApp.forEachLocalMember((Element e) {
kasperl 2013/03/06 10:26:51 Maybe add a comment here that briefly outlines wha
ahe 2013/03/06 16:01:41 Done.
92 for (Element dependency in allElementsResolvedFrom(e)) {
93 if (isExplicitlyDeferred(dependency)) {
94 deferredElements.putIfAbsent(dependency.getLibrary(),
kasperl 2013/03/06 10:26:51 I think this would be easier to read if you pulled
ahe 2013/03/06 16:01:41 Done.
95 () => new LinkedHashSet<Element>())
96 .add(dependency);
97 } else if (mainApp != dependency.getLibrary()) {
98 eagerElements.add(dependency);
99 }
100 }
101 });
102
103 eagerElements.addAll(compiler.globalDependencies.backendDependencies);
104
105 computeTransitiveClosure(eagerElements);
106
107 for (Set<Element> e in deferredElements.values) {
108 computeTransitiveClosure(e);
109 e.removeAll(eagerElements);
110 for (Element element in e) {
111 this.deferredElements.add(element);
112 }
113 }
114
kasperl 2013/03/06 10:26:51 Too many newlines.
ahe 2013/03/06 16:01:41 Done.
115
116 // Pseudo code to be implemented:
kasperl 2013/03/06 10:26:51 Not sure I understand how to review this based on
ahe 2013/03/06 16:01:41 I updated the comment to be a TODO. Hope it is cle
117 Map<Element, List<LibraryElement>> reverseMap =
118 new LinkedHashMap<Element, List<LibraryElement>>();
119
120 deferredElements.forEach((LibraryElement lib, Set<Element> map) {
121 for (Element e in map) {
122 reverseMap.putIfAbsent(e,
kasperl 2013/03/06 10:26:51 You an extra local here too?
ahe 2013/03/06 16:01:41 Done.
123 () => <LibraryElement>[]).add(lib);
124 }
125 });
126
127 // Now compute the output files based on the lists in reverseMap.
kasperl 2013/03/06 10:26:51 Change to a TODO or add the code?
ahe 2013/03/06 16:01:41 Done.
128
75 }); 129 });
76 } 130 }
77 131
132 /// Returns all elements in the tree map of [element], but not the
133 /// transitive closure.
134 Set<Element> allElementsResolvedFrom(Element element) {
135 element = element.implementation;
136 // TODO(ahe): This doesn't work. I need to record classes and
kasperl 2013/03/06 10:26:51 Hmm. The code seems to deal with classes, statics,
ahe 2013/03/06 16:01:41 This was an old note to myself I forgot to remove.
137 // top-level functions, but I only record constructors.
138 Set<Element> result = new LinkedHashSet<Element>();
139 if (element.isGenerativeConstructor()) {
140 element = element.getEnclosingClass();
141 }
142 if (element.isClass()) {
143 ClassElement cls = element;
144 cls.forEachLocalMember((Element e) {
145 result.addAll(DependencyCollector.collect(e, compiler));
146 });
147 for (var type in cls.allSupertypes) {
148 result.add(type.element);
149 }
150 result.add(cls);
151 } else if (Elements.isStaticOrTopLevel(element)) {
152 result.addAll(DependencyCollector.collect(element, compiler));
153 }
154 return result;
155 }
156
157 void computeTransitiveClosure(Set<Element> elements) {
kasperl 2013/03/06 10:26:51 The method names makes it sound like you'll be ret
ahe 2013/03/06 16:01:41 Done.
158 Set<Element> workSet = new LinkedHashSet.from(elements);
159 Set<Element> closure = new LinkedHashSet<Element>();
160 while (!workSet.isEmpty) {
161 Element current = workSet.first;
162 workSet.remove(current);
163 if (closure.contains(current)) continue;
164 workSet.addAll(allElementsResolvedFrom(current));
165 closure.add(current);
166 }
167 elements.addAll(closure);
168 }
169
78 Link<LibraryElement> findDeferredLibraries(LibraryElement library) { 170 Link<LibraryElement> findDeferredLibraries(LibraryElement library) {
79 Link<LibraryElement> link = const Link<LibraryElement>(); 171 Link<LibraryElement> link = const Link<LibraryElement>();
80 for (LibraryTag tag in library.tags) { 172 for (LibraryTag tag in library.tags) {
81 Link<MetadataAnnotation> metadata = tag.metadata; 173 Link<MetadataAnnotation> metadata = tag.metadata;
82 if (metadata == null) continue; 174 if (metadata == null) continue;
83 for (MetadataAnnotation metadata in tag.metadata) { 175 for (MetadataAnnotation metadata in tag.metadata) {
84 metadata.ensureResolved(compiler); 176 metadata.ensureResolved(compiler);
85 Element element = metadata.value.computeType(compiler).element; 177 Element element = metadata.value.computeType(compiler).element;
86 if (element == deferredLibraryClass) { 178 if (element == deferredLibraryClass) {
87 ConstructedConstant value = metadata.value; 179 ConstructedConstant value = metadata.value;
88 StringConstant nameField = value.fields[0]; 180 StringConstant nameField = value.fields[0];
89 SourceString expectedName = nameField.toDartString().source; 181 SourceString expectedName = nameField.toDartString().source;
90 LibraryElement deferredLibrary = library.getLibraryFromTag(tag); 182 LibraryElement deferredLibrary = library.getLibraryFromTag(tag);
91 link = link.prepend(deferredLibrary); 183 link = link.prepend(deferredLibrary);
92 SourceString actualName = 184 SourceString actualName =
93 new SourceString(deferredLibrary.getLibraryOrScriptName()); 185 new SourceString(deferredLibrary.getLibraryOrScriptName());
94 if (expectedName != actualName) { 186 if (expectedName != actualName) {
95 compiler.reportErrorCode( 187 compiler.reportErrorCode(
96 metadata, 188 metadata,
97 MessageKind.DEFERRED_LIBRARY_NAME_MISMATCH, 189 MessageKind.DEFERRED_LIBRARY_NAME_MISMATCH,
98 { 'expectedName': expectedName.slowToString(), 190 { 'expectedName': expectedName.slowToString(),
99 'actualName': actualName.slowToString()}); 191 'actualName': actualName.slowToString()});
100 } 192 }
101 } 193 }
102 } 194 }
103 } 195 }
104 return link; 196 return link;
105 } 197 }
106 } 198 }
199
200 class DependencyCollector extends Visitor {
201 final Set<Element> dependencies = new LinkedHashSet<Element>();
202 final TreeElements elements;
203 final Compiler compiler;
204
205 DependencyCollector(this.elements, this.compiler);
206
207 visitNode(Node node) {
208 Element dependency = elements[node];
209 if (dependency != null) {
210 TreeElements elements =
211 compiler.enqueuer.resolution.getCachedElements(dependency);
212 if (elements != null) {
213 dependencies.add(elements.currentElement);
214 }
215 }
216 node.visitChildren(this);
217 }
218
219 static Set<Element> collect(Element element, Compiler compiler) {
220 TreeElements elements =
221 compiler.enqueuer.resolution.getCachedElements(element);
222 if (elements == null) return new LinkedHashSet<Element>();
223 Node node = element.parseNode(compiler);
224 var collector = new DependencyCollector(elements, compiler);
225 node.accept(collector);
226 collector.dependencies.addAll(elements.backendDependencies);
227 return collector.dependencies;
228 }
229 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698