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

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

Issue 350693007: Load patches via callback. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix caching_compiler Created 6 years, 6 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) 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 part of dart2js; 5 library dart2js.library_loader;
6
7 import 'dart:async';
8 import 'dart2jslib.dart'
9 show Compiler,
10 CompilerTask,
11 MessageKind,
12 Script,
13 invariant;
14 import 'elements/elements.dart'
15 show CompilationUnitElement,
16 Element,
17 LibraryElement,
18 PrefixElement;
19 import 'elements/modelx.dart'
20 show CompilationUnitElementX,
21 DeferredLoaderGetterElementX,
22 ErroneousElementX,
23 LibraryElementX,
24 PrefixElementX;
25 import 'helpers/helpers.dart';
26 import 'native_handler.dart' as native;
27 import 'tree/tree.dart';
28 import 'util/util.dart' show Link, LinkBuilder;
6 29
7 /** 30 /**
8 * [CompilerTask] for loading libraries and setting up the import/export scopes. 31 * [CompilerTask] for loading libraries and setting up the import/export scopes.
9 * 32 *
10 * The library loader uses four different kinds of URIs in different parts of 33 * The library loader uses four different kinds of URIs in different parts of
11 * the loading process. 34 * the loading process.
12 * 35 *
13 * ## User URI ## 36 * ## User URI ##
14 * 37 *
15 * A 'user URI' is a URI provided by the user in code and as the main entry URI 38 * A 'user URI' is a URI provided by the user in code and as the main entry URI
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 * The distinction between readable URI and resource URI is necessary to ensure 113 * The distinction between readable URI and resource URI is necessary to ensure
91 * that these imports 114 * that these imports
92 * 115 *
93 * import 'package:foo.dart' as a; 116 * import 'package:foo.dart' as a;
94 * import 'packages/foo.dart' as b; 117 * import 'packages/foo.dart' as b;
95 * 118 *
96 * do _not_ resolve to the same library when the package root URI happens to 119 * do _not_ resolve to the same library when the package root URI happens to
97 * point to the 'packages' folder. 120 * point to the 'packages' folder.
98 * 121 *
99 */ 122 */
100 abstract class LibraryLoader extends CompilerTask { 123 abstract class LibraryLoaderTask implements CompilerTask {
101 LibraryLoader(Compiler compiler) : super(compiler); 124 factory LibraryLoaderTask(Compiler compiler) = _LibraryLoaderTask;
102 125
103 /** 126 /**
104 * Loads the library specified by the [resolvedUri] and returns its 127 * Loads the library specified by the [resolvedUri] and returns its
105 * [LibraryElement]. 128 * [LibraryElement].
106 * 129 *
107 * If the library is not already loaded, the method creates the 130 * If the library is not already loaded, the method creates the
108 * [LibraryElement] for the library and computes the import/export scope, 131 * [LibraryElement] for the library and computes the import/export scope,
109 * loading and computing the import/export scopes of all required libraries in 132 * loading and computing the import/export scopes of all required libraries in
110 * the process. The method handles cyclic dependency between libraries. 133 * the process. The method handles cyclic dependency between libraries.
111 *
112 * This is the main entry point for [LibraryLoader].
113 */ 134 */
114 Future<LibraryElement> loadLibrary(Uri resolvedUri); 135 Future<LibraryElement> loadLibrary(Uri resolvedUri);
115 136
116 // TODO(johnniwinther): Remove this when patches don't need special parsing. 137 /// Reset the library loader task to prepare for compilation. This is used
117 Future registerLibraryFromTag(LibraryDependencyHandler handler, 138 /// for incremental compilation.
118 LibraryElement library, 139 void reset();
119 LibraryDependency tag); 140
141 /// Reuse [library] from a previous compilation. This is used for incremental
142 /// compilation.
143 void reuseLibrary(LibraryElement library);
144 }
145
146 /// Handle for creating synthesized/patch libraries during library loading.
147 abstract class LibraryLoader {
148 /// This method must be called when a new synthesized/patch library has been
149 /// created to ensure that [library] will part of library dependency graph
150 /// used for computing import/export scopes.
151 void registerNewLibrary(LibraryElement library);
152
153 /// This method must be called when a new synthesized/patch library has been
154 /// scanned in order to process the library tags in [library] and thus handle
155 /// imports/exports/parts in the synthesized/patch library.
156 Future processLibraryTags(LibraryElement library);
120 } 157 }
121 158
122 /** 159 /**
123 * [CombinatorFilter] is a succinct representation of a list of combinators from 160 * [CombinatorFilter] is a succinct representation of a list of combinators from
124 * a library dependency tag. 161 * a library dependency tag.
125 */ 162 */
126 class CombinatorFilter { 163 class CombinatorFilter {
127 const CombinatorFilter(); 164 const CombinatorFilter();
128 165
129 /** 166 /**
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 HideFilter(this.excludedNames); 235 HideFilter(this.excludedNames);
199 236
200 bool exclude(Element element) => excludedNames.contains(element.name); 237 bool exclude(Element element) => excludedNames.contains(element.name);
201 } 238 }
202 239
203 /** 240 /**
204 * Implementation class for [LibraryLoader]. The distinction between 241 * Implementation class for [LibraryLoader]. The distinction between
205 * [LibraryLoader] and [LibraryLoaderTask] is made to hide internal members from 242 * [LibraryLoader] and [LibraryLoaderTask] is made to hide internal members from
206 * the [LibraryLoader] interface. 243 * the [LibraryLoader] interface.
207 */ 244 */
208 class LibraryLoaderTask extends LibraryLoader { 245 class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
209 LibraryLoaderTask(Compiler compiler) : super(compiler); 246 _LibraryLoaderTask(Compiler compiler) : super(compiler);
210 String get name => 'LibraryLoader'; 247 String get name => 'LibraryLoader';
211 248
212 final Map<Uri, LibraryElement> libraryResourceUriMap = 249 final Map<Uri, LibraryElement> libraryResourceUriMap =
213 new Map<Uri, LibraryElement>(); 250 new Map<Uri, LibraryElement>();
214 final Map<String, LibraryElement> libraryNames = 251 final Map<String, LibraryElement> libraryNames =
215 new Map<String, LibraryElement>(); 252 new Map<String, LibraryElement>();
216 253
217 LibraryDependencyHandler currentHandler; 254 LibraryDependencyHandler currentHandler;
218 255
256 void reset() {
257 assert(currentHandler == null);
258 libraryResourceUriMap.clear();
259 libraryNames.clear();
260 }
261
262 void reuseLibrary(LibraryElement library) {
263 String name = library.getLibraryOrScriptName();
264 Uri resourceUri = library.entryCompilationUnit.script.resourceUri;
265 libraryResourceUriMap[resourceUri] = library;
266 libraryNames[name] = library;
267 }
268
219 Future<LibraryElement> loadLibrary(Uri resolvedUri) { 269 Future<LibraryElement> loadLibrary(Uri resolvedUri) {
220 return measure(() { 270 return measure(() {
221 assert(currentHandler == null); 271 assert(currentHandler == null);
222 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the 272 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the
223 // loading of a library cluster. 273 // loading of a library cluster.
224 currentHandler = new LibraryDependencyHandler(compiler); 274 currentHandler = new LibraryDependencyHandler(this);
225 return createLibrary(currentHandler, null, resolvedUri) 275 return createLibrary(currentHandler, null, resolvedUri)
226 .then((LibraryElement library) { 276 .then((LibraryElement library) {
227 return compiler.withCurrentElement(library, () { 277 return compiler.withCurrentElement(library, () {
228 return measure(() { 278 return measure(() {
229 currentHandler.computeExports(); 279 currentHandler.computeExports();
230 Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; 280 Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{};
231 currentHandler.loadedLibraries.forEach( 281 currentHandler.loadedLibraries.forEach(
232 (LibraryElement loadedLibrary) { 282 (LibraryElement loadedLibrary) {
233 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; 283 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary;
234 }); 284 });
(...skipping 28 matching lines...) Expand all
263 MessageKind.GENERIC, {'text': 'Error: Out of order.'}); 313 MessageKind.GENERIC, {'text': 'Error: Out of order.'});
264 return tagState; 314 return tagState;
265 } 315 }
266 return TagState.NEXT[value]; 316 return TagState.NEXT[value];
267 } 317 }
268 318
269 bool importsDartCore = false; 319 bool importsDartCore = false;
270 var libraryDependencies = new LinkBuilder<LibraryDependency>(); 320 var libraryDependencies = new LinkBuilder<LibraryDependency>();
271 Uri base = library.entryCompilationUnit.script.readableUri; 321 Uri base = library.entryCompilationUnit.script.readableUri;
272 322
273 // TODO(rnystrom): Remove .toList() here if #11523 is fixed. 323 // TODO(johnniwinther): Reverse the tag list on access and cache the result.
274 return Future.forEach(library.tags.reverse().toList(), (LibraryTag tag) { 324 return Future.forEach(library.tags.reverse().toList(), (LibraryTag tag) {
275 return compiler.withCurrentElement(library, () { 325 return compiler.withCurrentElement(library, () {
276 if (tag.isImport) { 326 if (tag.isImport) {
277 Import import = tag; 327 Import import = tag;
278 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); 328 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import);
279 if (import.uri.dartString.slowToString() == 'dart:core') { 329 if (import.uri.dartString.slowToString() == 'dart:core') {
280 importsDartCore = true; 330 importsDartCore = true;
281 } 331 }
282 libraryDependencies.addLast(import); 332 libraryDependencies.addLast(import);
283 } else if (tag.isExport) { 333 } else if (tag.isExport) {
(...skipping 10 matching lines...) Expand all
294 Part part = tag; 344 Part part = tag;
295 StringNode uri = part.uri; 345 StringNode uri = part.uri;
296 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); 346 Uri resolvedUri = base.resolve(uri.dartString.slowToString());
297 tagState = checkTag(TagState.SOURCE, part); 347 tagState = checkTag(TagState.SOURCE, part);
298 return scanPart(part, resolvedUri, library); 348 return scanPart(part, resolvedUri, library);
299 } else { 349 } else {
300 compiler.internalError(tag, "Unhandled library tag."); 350 compiler.internalError(tag, "Unhandled library tag.");
301 } 351 }
302 }); 352 });
303 }).then((_) { 353 }).then((_) {
304 // TODO(johnniwinther): Move callback to after patching. 354 return compiler.onLibraryScanned(library, handler);
305 compiler.onLibraryScanned(library); 355 }).then((_) {
306 return compiler.withCurrentElement(library, () { 356 return compiler.withCurrentElement(library, () {
307 checkDuplicatedLibraryName(library); 357 checkDuplicatedLibraryName(library);
308 // Apply patch, if any. 358
309 if (library.isPlatformLibrary) {
310 return patchDartLibrary(handler, library, library.canonicalUri.path);
311 }
312 });
313 }).then((_) {
314 return compiler.withCurrentElement(library, () {
315 // Import dart:core if not already imported. 359 // Import dart:core if not already imported.
316 if (!importsDartCore && !isDartCore(library.canonicalUri)) { 360 if (!importsDartCore && !isDartCore(library.canonicalUri)) {
317 return loadCoreLibrary(handler).then((LibraryElement coreLibrary) { 361 return loadCoreLibrary(handler).then((LibraryElement coreLibrary) {
318 handler.registerDependency(library, null, coreLibrary); 362 handler.registerDependency(library, null, coreLibrary);
319 }); 363 });
320 } 364 }
321 }); 365 });
322 }).then((_) { 366 }).then((_) {
323 // TODO(rnystrom): Remove .toList() here if #11523 is fixed.
324 return Future.forEach(libraryDependencies.toLink().toList(), (tag) { 367 return Future.forEach(libraryDependencies.toLink().toList(), (tag) {
325 return compiler.withCurrentElement(library, () { 368 return compiler.withCurrentElement(library, () {
326 return registerLibraryFromTag(handler, library, tag); 369 return registerLibraryFromTag(handler, library, tag);
327 }); 370 });
328 }); 371 });
329 }); 372 });
330 } 373 }
331 374
332 void checkDuplicatedLibraryName(LibraryElement library) { 375 void checkDuplicatedLibraryName(LibraryElement library) {
333 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; 376 Uri resourceUri = library.entryCompilationUnit.script.resourceUri;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 return new Future.value(compiler.coreLibrary); 422 return new Future.value(compiler.coreLibrary);
380 } 423 }
381 424
382 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); 425 Uri coreUri = new Uri(scheme: 'dart', path: 'core');
383 return createLibrary(handler, null, coreUri).then((LibraryElement library) { 426 return createLibrary(handler, null, coreUri).then((LibraryElement library) {
384 compiler.coreLibrary = library; 427 compiler.coreLibrary = library;
385 return library; 428 return library;
386 }); 429 });
387 } 430 }
388 431
389 Future patchDartLibrary(LibraryDependencyHandler handler,
390 LibraryElement library,
391 String dartLibraryPath) {
392 if (library.isPatched) return new Future.value();
393 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath);
394 if (patchUri == null) return new Future.value();
395
396 return compiler.patchParser.patchLibrary(handler, patchUri, library);
397 }
398
399 /** 432 /**
400 * Handle a part tag in the scope of [library]. The [resolvedUri] given is 433 * Handle a part tag in the scope of [library]. The [resolvedUri] given is
401 * used as is, any URI resolution should be done beforehand. 434 * used as is, any URI resolution should be done beforehand.
402 */ 435 */
403 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) { 436 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) {
404 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); 437 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri);
405 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); 438 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part);
406 if (readableUri == null) return new Future.value(); 439 if (readableUri == null) return new Future.value();
407 return compiler.withCurrentElement(library, () { 440 return compiler.withCurrentElement(library, () {
408 return compiler.readScript(part, readableUri). 441 return compiler.readScript(part, readableUri).
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 LibraryElement library = compiler.libraries[resolvedUri.toString()]; 491 LibraryElement library = compiler.libraries[resolvedUri.toString()];
459 if (library != null) { 492 if (library != null) {
460 return new Future.value(library); 493 return new Future.value(library);
461 } 494 }
462 return compiler.withCurrentElement(importingLibrary, () { 495 return compiler.withCurrentElement(importingLibrary, () {
463 return compiler.readScript(node, readableUri) 496 return compiler.readScript(node, readableUri)
464 .then((Script script) { 497 .then((Script script) {
465 if (script == null) return null; 498 if (script == null) return null;
466 LibraryElement element = new LibraryElementX(script, resolvedUri); 499 LibraryElement element = new LibraryElementX(script, resolvedUri);
467 compiler.withCurrentElement(element, () { 500 compiler.withCurrentElement(element, () {
468 compiler.onLibraryCreated(element);
469 handler.registerNewLibrary(element); 501 handler.registerNewLibrary(element);
470 native.maybeEnableNative(compiler, element); 502 native.maybeEnableNative(compiler, element);
471 compiler.libraries[resolvedUri.toString()] = element; 503 compiler.libraries[resolvedUri.toString()] = element;
472 compiler.scanner.scanLibrary(element); 504 compiler.scanner.scanLibrary(element);
473 }); 505 });
474 return processLibraryTags(handler, element).then((_) { 506 return processLibraryTags(handler, element).then((_) {
475 compiler.withCurrentElement(element, () { 507 compiler.withCurrentElement(element, () {
476 handler.registerLibraryExports(element); 508 handler.registerLibraryExports(element);
477 }); 509 });
478 return element; 510 return element;
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 } 832 }
801 833
802 /** 834 /**
803 * Helper class used for computing the possibly cyclic import/export scopes of 835 * Helper class used for computing the possibly cyclic import/export scopes of
804 * a set of libraries. 836 * a set of libraries.
805 * 837 *
806 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded 838 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded
807 * libraries and to compute their import/export scopes through a fixed-point 839 * libraries and to compute their import/export scopes through a fixed-point
808 * algorithm. 840 * algorithm.
809 */ 841 */
810 class LibraryDependencyHandler { 842 class LibraryDependencyHandler implements LibraryLoader {
811 final Compiler compiler; 843 final _LibraryLoaderTask task;
812 844
813 /** 845 /**
814 * Newly loaded libraries and their corresponding node in the library 846 * Newly loaded libraries and their corresponding node in the library
815 * dependency graph. Libraries that have already been fully loaded are not 847 * dependency graph. Libraries that have already been fully loaded are not
816 * part of the dependency graph of this handler since their export scopes have 848 * part of the dependency graph of this handler since their export scopes have
817 * already been computed. 849 * already been computed.
818 */ 850 */
819 Map<LibraryElement, LibraryDependencyNode> nodeMap = 851 Map<LibraryElement, LibraryDependencyNode> nodeMap =
820 new Map<LibraryElement, LibraryDependencyNode>(); 852 new Map<LibraryElement, LibraryDependencyNode>();
821 853
822 LibraryDependencyHandler(Compiler this.compiler); 854 LibraryDependencyHandler(this.task);
855
856 Compiler get compiler => task.compiler;
823 857
824 /// The libraries loaded with this handler. 858 /// The libraries loaded with this handler.
825 Iterable<LibraryElement> get loadedLibraries => nodeMap.keys; 859 Iterable<LibraryElement> get loadedLibraries => nodeMap.keys;
826 860
827 /** 861 /**
828 * Performs a fixed-point computation on the export scopes of all registered 862 * Performs a fixed-point computation on the export scopes of all registered
829 * libraries and creates the import/export of the libraries based on the 863 * libraries and creates the import/export of the libraries based on the
830 * fixed-point. 864 * fixed-point.
831 */ 865 */
832 void computeExports() { 866 void computeExports() {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 message: "$library has not been registered")); 935 message: "$library has not been registered"));
902 importingNode.registerImportDependency(tag, loadedLibrary); 936 importingNode.registerImportDependency(tag, loadedLibrary);
903 } 937 }
904 } 938 }
905 939
906 /** 940 /**
907 * Registers [library] for the processing of its import/export scope. 941 * Registers [library] for the processing of its import/export scope.
908 */ 942 */
909 void registerNewLibrary(LibraryElement library) { 943 void registerNewLibrary(LibraryElement library) {
910 nodeMap[library] = new LibraryDependencyNode(library); 944 nodeMap[library] = new LibraryDependencyNode(library);
945 compiler.onLibraryCreated(library);
911 } 946 }
912 947
913 /** 948 /**
914 * Registers all top-level entities of [library] as starting point for the 949 * Registers all top-level entities of [library] as starting point for the
915 * fixed-point computation of the import/export scopes. 950 * fixed-point computation of the import/export scopes.
916 */ 951 */
917 void registerLibraryExports(LibraryElement library) { 952 void registerLibraryExports(LibraryElement library) {
918 nodeMap[library].registerInitialExports(); 953 nodeMap[library].registerInitialExports();
919 } 954 }
955
956 Future processLibraryTags(LibraryElement library) {
957 return task.processLibraryTags(this, library);
958 }
920 } 959 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698