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

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

Issue 17759007: First pass at asynchronous input loading in dart2js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 7 years, 3 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 part of dart2js;
6 6
7 /** 7 /**
8 * [CompilerTask] for loading libraries and setting up the import/export scopes. 8 * [CompilerTask] for loading libraries and setting up the import/export scopes.
9 * 9 *
10 * The library loader uses four different kinds of URIs in different parts of 10 * The library loader uses four different kinds of URIs in different parts of
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 * 106 *
107 * If the library is not already loaded, the method creates the 107 * If the library is not already loaded, the method creates the
108 * [LibraryElement] for the library and computes the import/export scope, 108 * [LibraryElement] for the library and computes the import/export scope,
109 * loading and computing the import/export scopes of all required libraries in 109 * loading and computing the import/export scopes of all required libraries in
110 * the process. The method handles cyclic dependency between libraries. 110 * the process. The method handles cyclic dependency between libraries.
111 * 111 *
112 * This is the main entry point for [LibraryLoader]. 112 * This is the main entry point for [LibraryLoader].
113 */ 113 */
114 // TODO(johnniwinther): Remove [canonicalUri] together with 114 // TODO(johnniwinther): Remove [canonicalUri] together with
115 // [Compiler.scanBuiltinLibrary]. 115 // [Compiler.scanBuiltinLibrary].
116 LibraryElement loadLibrary(Uri resolvedUri, Node node, Uri canonicalUri); 116 Future<LibraryElement> loadLibrary(Uri resolvedUri, Node node,
117 Uri canonicalUri);
117 118
118 // TODO(johnniwinther): Remove this when patches don't need special parsing. 119 // TODO(johnniwinther): Remove this when patches don't need special parsing.
119 void registerLibraryFromTag(LibraryDependencyHandler handler, 120 Future registerLibraryFromTag(LibraryDependencyHandler handler,
120 LibraryElement library, 121 LibraryElement library,
121 LibraryDependency tag); 122 LibraryDependency tag);
122 123
123 /** 124 /**
124 * Adds the elements in the export scope of [importedLibrary] to the import 125 * Adds the elements in the export scope of [importedLibrary] to the import
125 * scope of [importingLibrary]. 126 * scope of [importingLibrary].
126 */ 127 */
127 // TODO(johnniwinther): Move handling of 'js_helper' to the library loader 128 // TODO(johnniwinther): Move handling of 'js_helper' to the library loader
128 // to remove this method from the [LibraryLoader] interface. 129 // to remove this method from the [LibraryLoader] interface.
129 void importLibrary(LibraryElement importingLibrary, 130 void importLibrary(LibraryElement importingLibrary,
130 LibraryElement importedLibrary, 131 LibraryElement importedLibrary,
131 Import tag); 132 Import tag);
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 class LibraryLoaderTask extends LibraryLoader { 221 class LibraryLoaderTask extends LibraryLoader {
221 LibraryLoaderTask(Compiler compiler) : super(compiler); 222 LibraryLoaderTask(Compiler compiler) : super(compiler);
222 String get name => 'LibraryLoader'; 223 String get name => 'LibraryLoader';
223 List onLibraryLoadedCallbacks = []; 224 List onLibraryLoadedCallbacks = [];
224 225
225 final Map<String, LibraryElement> libraryNames = 226 final Map<String, LibraryElement> libraryNames =
226 new LinkedHashMap<String, LibraryElement>(); 227 new LinkedHashMap<String, LibraryElement>();
227 228
228 LibraryDependencyHandler currentHandler; 229 LibraryDependencyHandler currentHandler;
229 230
230 LibraryElement loadLibrary(Uri resolvedUri, Node node, Uri canonicalUri) { 231 Future<LibraryElement> loadLibrary(Uri resolvedUri, Node node,
232 Uri canonicalUri) {
231 return measure(() { 233 return measure(() {
232 assert(currentHandler == null); 234 assert(currentHandler == null);
233 currentHandler = new LibraryDependencyHandler(compiler); 235 currentHandler = new LibraryDependencyHandler(compiler);
ahe 2013/09/02 13:43:24 This is nasty. I suggest you document that current
Johnni Winther 2013/09/03 07:51:39 Done.
234 LibraryElement library = 236 return createLibrary(currentHandler, null, resolvedUri, node,
235 createLibrary(currentHandler, null, resolvedUri, node, canonicalUri); 237 canonicalUri).then((LibraryElement library) {
236 currentHandler.computeExports(); 238 return compiler.withCurrentElement(library, () {
237 currentHandler = null; 239 return measure(() {
238 var workList = onLibraryLoadedCallbacks; 240 currentHandler.computeExports();
239 onLibraryLoadedCallbacks = []; 241 currentHandler = null;
240 workList.forEach((f) => f()); 242 var workList = onLibraryLoadedCallbacks;
241 return library; 243 onLibraryLoadedCallbacks = [];
244 return Future.forEach(workList, (f) => f()).then((_) => library);
245 });
246 });
247 });
242 }); 248 });
243 } 249 }
244 250
245 /** 251 /**
246 * Processes the library tags in [library]. 252 * Processes the library tags in [library].
247 * 253 *
248 * The imported/exported libraries are loaded and processed recursively but 254 * The imported/exported libraries are loaded and processed recursively but
249 * the import/export scopes are not set up. 255 * the import/export scopes are not set up.
250 */ 256 */
251 void processLibraryTags(LibraryDependencyHandler handler, 257 Future processLibraryTags(LibraryDependencyHandler handler,
252 LibraryElement library) { 258 LibraryElement library) {
253 int tagState = TagState.NO_TAG_SEEN; 259 int tagState = TagState.NO_TAG_SEEN;
254 260
255 /** 261 /**
256 * If [value] is less than [tagState] complain and return 262 * If [value] is less than [tagState] complain and return
257 * [tagState]. Otherwise return the new value for [tagState] 263 * [tagState]. Otherwise return the new value for [tagState]
258 * (transition function for state machine). 264 * (transition function for state machine).
259 */ 265 */
260 int checkTag(int value, LibraryTag tag) { 266 int checkTag(int value, LibraryTag tag) {
261 if (tagState > value) { 267 if (tagState > value) {
262 compiler.reportFatalError( 268 compiler.reportFatalError(
263 tag, 269 tag,
264 MessageKind.GENERIC, {'text': 'Error: Out of order.'}); 270 MessageKind.GENERIC, {'text': 'Error: Out of order.'});
265 return tagState; 271 return tagState;
266 } 272 }
267 return TagState.NEXT[value]; 273 return TagState.NEXT[value];
268 } 274 }
269 275
270 bool importsDartCore = false; 276 bool importsDartCore = false;
271 var libraryDependencies = new LinkBuilder<LibraryDependency>(); 277 var libraryDependencies = new LinkBuilder<LibraryDependency>();
272 Uri base = library.entryCompilationUnit.script.uri; 278 Uri base = library.entryCompilationUnit.script.uri;
273 for (LibraryTag tag in library.tags.reverse()) { 279
274 if (tag.isImport) { 280 // TODO(rnystrom): Remove .toList() here if #11523 is fixed.
275 Import import = tag; 281 return Future.forEach(library.tags.reverse().toList(), (LibraryTag tag) {
276 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); 282 compiler.withCurrentElement(library, () {
277 if (import.uri.dartString.slowToString() == 'dart:core') { 283 if (tag.isImport) {
278 importsDartCore = true; 284 Import import = tag;
285 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import);
286 if (import.uri.dartString.slowToString() == 'dart:core') {
287 importsDartCore = true;
288 }
289 libraryDependencies.addLast(import);
290 } else if (tag.isExport) {
291 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag);
292 libraryDependencies.addLast(tag);
293 } else if (tag.isLibraryName) {
294 tagState = checkTag(TagState.LIBRARY, tag);
295 if (library.libraryTag != null) {
296 compiler.cancel("duplicated library declaration", node: tag);
297 } else {
298 library.libraryTag = tag;
299 }
300 checkDuplicatedLibraryName(library);
301 } else if (tag.isPart) {
302 Part part = tag;
303 StringNode uri = part.uri;
304 Uri resolvedUri = base.resolve(uri.dartString.slowToString());
305 tagState = checkTag(TagState.SOURCE, part);
306 return scanPart(part, resolvedUri, library);
307 } else {
308 compiler.internalError("Unhandled library tag.", node: tag);
279 } 309 }
280 libraryDependencies.addLast(import); 310 });
281 } else if (tag.isExport) { 311 }).then((_) {
282 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag); 312 return compiler.withCurrentElement(library, () {
283 libraryDependencies.addLast(tag); 313 // Apply patch, if any.
284 } else if (tag.isLibraryName) { 314 if (library.isPlatformLibrary) {
285 tagState = checkTag(TagState.LIBRARY, tag); 315 return patchDartLibrary(handler, library, library.canonicalUri.path);
286 if (library.libraryTag != null) {
287 compiler.cancel("duplicated library declaration", node: tag);
288 } else {
289 library.libraryTag = tag;
290 } 316 }
291 checkDuplicatedLibraryName(library); 317 });
292 } else if (tag.isPart) { 318 }).then((_) {
293 Part part = tag; 319 return compiler.withCurrentElement(library, () {
294 StringNode uri = part.uri; 320 // Import dart:core if not already imported.
295 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); 321 if (!importsDartCore && !isDartCore(library.canonicalUri)) {
296 tagState = checkTag(TagState.SOURCE, part); 322 return loadCoreLibrary(handler).then((LibraryElement coreLibrary) {
297 scanPart(part, resolvedUri, library); 323 handler.registerDependency(library, null, coreLibrary);
298 } else { 324 });
299 compiler.internalError("Unhandled library tag.", node: tag); 325 }
300 } 326 });
301 } 327 }).then((_) {
302 328 // TODO(rnystrom): Remove .toList() here if #11523 is fixed.
303 // Apply patch, if any. 329 return Future.forEach(libraryDependencies.toLink().toList(), (tag) {
304 if (library.isPlatformLibrary) { 330 return compiler.withCurrentElement(library, () {
305 patchDartLibrary(handler, library, library.canonicalUri.path); 331 return registerLibraryFromTag(handler, library, tag);
306 } 332 });
307 333 });
308 // Import dart:core if not already imported. 334 });
309 if (!importsDartCore && !isDartCore(library.canonicalUri)) {
310 handler.registerDependency(library, null, loadCoreLibrary(handler));
311 }
312
313 for (LibraryDependency tag in libraryDependencies.toLink()) {
314 registerLibraryFromTag(handler, library, tag);
315 }
316 } 335 }
317 336
318 void checkDuplicatedLibraryName(LibraryElement library) { 337 void checkDuplicatedLibraryName(LibraryElement library) {
319 LibraryName tag = library.libraryTag; 338 LibraryName tag = library.libraryTag;
320 if (tag != null) { 339 if (tag != null) {
321 String name = library.getLibraryOrScriptName(); 340 String name = library.getLibraryOrScriptName();
322 LibraryElement existing = 341 LibraryElement existing =
323 libraryNames.putIfAbsent(name, () => library); 342 libraryNames.putIfAbsent(name, () => library);
324 if (!identical(existing, library)) { 343 if (!identical(existing, library)) {
325 Uri uri = library.entryCompilationUnit.script.uri; 344 Uri uri = library.entryCompilationUnit.script.uri;
326 compiler.reportMessage( 345 compiler.reportMessage(
327 compiler.spanFromSpannable(tag.name, uri), 346 compiler.spanFromSpannable(tag.name, uri),
328 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), 347 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}),
329 api.Diagnostic.WARNING); 348 api.Diagnostic.WARNING);
330 Uri existingUri = existing.entryCompilationUnit.script.uri; 349 Uri existingUri = existing.entryCompilationUnit.script.uri;
331 compiler.reportMessage( 350 compiler.reportMessage(
332 compiler.spanFromSpannable(existing.libraryTag.name, existingUri), 351 compiler.spanFromSpannable(existing.libraryTag.name, existingUri),
333 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), 352 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}),
334 api.Diagnostic.WARNING); 353 api.Diagnostic.WARNING);
335 } 354 }
336 } 355 }
337 } 356 }
338 357
339 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core"; 358 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core";
340 359
341 /** 360 /**
342 * Lazily loads and returns the [LibraryElement] for the dart:core library. 361 * Lazily loads and returns the [LibraryElement] for the dart:core library.
343 */ 362 */
344 LibraryElement loadCoreLibrary(LibraryDependencyHandler handler) { 363 Future<LibraryElement> loadCoreLibrary(LibraryDependencyHandler handler) {
345 if (compiler.coreLibrary == null) { 364 if (compiler.coreLibrary != null) {
346 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); 365 return new Future.value(compiler.coreLibrary);
347 compiler.coreLibrary
348 = createLibrary(handler, null, coreUri, null, coreUri);
349 } 366 }
350 return compiler.coreLibrary; 367
368 Uri coreUri = new Uri(scheme: 'dart', path: 'core');
369 return createLibrary(handler, null, coreUri, null, coreUri)
370 .then((LibraryElement library) {
371 compiler.coreLibrary = library;
372 return library;
373 });
351 } 374 }
352 375
353 void patchDartLibrary(LibraryDependencyHandler handler, 376 Future patchDartLibrary(LibraryDependencyHandler handler,
354 LibraryElement library, String dartLibraryPath) { 377 LibraryElement library, String dartLibraryPath) {
355 if (library.isPatched) return; 378 if (library.isPatched) return new Future.value();
356 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); 379 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath);
357 if (patchUri != null) { 380 if (patchUri == null) return new Future.value();
358 compiler.patchParser.patchLibrary(handler, patchUri, library); 381
359 } 382 return compiler.patchParser.patchLibrary(handler, patchUri, library);
360 } 383 }
361 384
362 /** 385 /**
363 * Handle a part tag in the scope of [library]. The [resolvedUri] given is 386 * Handle a part tag in the scope of [library]. The [resolvedUri] given is
364 * used as is, any URI resolution should be done beforehand. 387 * used as is, any URI resolution should be done beforehand.
365 */ 388 */
366 void scanPart(Part part, Uri resolvedUri, LibraryElement library) { 389 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) {
367 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); 390 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri);
368 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); 391 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part);
369 if (readableUri == null) return; 392 if (readableUri == null) return new Future.value();
370 Script sourceScript = compiler.readScript(readableUri, part); 393 return compiler.readScript(readableUri, library, part).
371 if (sourceScript == null) return; 394 then((Script sourceScript) {
372 CompilationUnitElement unit = 395 if (sourceScript == null) return;
373 new CompilationUnitElementX(sourceScript, library); 396 CompilationUnitElement unit =
374 compiler.withCurrentElement(unit, () { 397 new CompilationUnitElementX(sourceScript, library);
375 compiler.scanner.scan(unit); 398 compiler.withCurrentElement(unit, () {
376 if (unit.partTag == null) { 399 compiler.scanner.scan(unit);
377 compiler.reportError(unit, MessageKind.MISSING_PART_OF_TAG); 400 if (unit.partTag == null) {
378 } 401 compiler.reportError(unit, MessageKind.MISSING_PART_OF_TAG);
379 }); 402 }
403 });
404 });
380 } 405 }
381 406
382 /** 407 /**
383 * Handle an import/export tag by loading the referenced library and 408 * Handle an import/export tag by loading the referenced library and
384 * registering its dependency in [handler] for the computation of the import/ 409 * registering its dependency in [handler] for the computation of the import/
385 * export scope. 410 * export scope.
386 */ 411 */
387 void registerLibraryFromTag(LibraryDependencyHandler handler, 412 Future registerLibraryFromTag(LibraryDependencyHandler handler,
388 LibraryElement library, 413 LibraryElement library,
389 LibraryDependency tag) { 414 LibraryDependency tag) {
390 Uri base = library.entryCompilationUnit.script.uri; 415 Uri base = library.entryCompilationUnit.script.uri;
391 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString()); 416 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString());
392 LibraryElement loadedLibrary = 417 return createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri)
393 createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri); 418 .then((LibraryElement loadedLibrary) {
394 if (loadedLibrary == null) return; 419 if (loadedLibrary == null) return;
395 handler.registerDependency(library, tag, loadedLibrary); 420 compiler.withCurrentElement(library, () {
421 handler.registerDependency(library, tag, loadedLibrary);
396 422
397 if (!loadedLibrary.hasLibraryName()) { 423 if (!loadedLibrary.hasLibraryName()) {
398 compiler.withCurrentElement(library, () { 424 compiler.reportFatalError(
399 compiler.reportFatalError( 425 tag == null ? null : tag.uri,
400 tag == null ? null : tag.uri, 426 MessageKind.GENERIC,
401 MessageKind.GENERIC, 427 {'text':
402 {'text': 428 'Error: No library name found in '
403 'Error: No library name found in ${loadedLibrary.canonicalUri}.'}); 429 '${loadedLibrary.canonicalUri}.'});
404 }); 430 }
405 } 431 });
432 });
406 } 433 }
407 434
408 /** 435 /**
409 * Create (or reuse) a library element for the library specified by the 436 * Create (or reuse) a library element for the library specified by the
410 * [resolvedUri]. 437 * [resolvedUri].
411 * 438 *
412 * If a new library is created, the [handler] is notified. 439 * If a new library is created, the [handler] is notified.
413 */ 440 */
414 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the 441 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the
415 // canonical uri when [Compiler.scanBuiltinLibrary] is removed. 442 // canonical uri when [Compiler.scanBuiltinLibrary] is removed.
416 LibraryElement createLibrary(LibraryDependencyHandler handler, 443 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler,
417 LibraryElement importingLibrary, 444 LibraryElement importingLibrary,
418 Uri resolvedUri, Node node, Uri canonicalUri) { 445 Uri resolvedUri, Node node, Uri canonicalUri) {
419 // TODO(johnniwinther): Create erroneous library elements for missing 446 // TODO(johnniwinther): Create erroneous library elements for missing
420 // libraries. 447 // libraries.
421 Uri readableUri = 448 Uri readableUri =
422 compiler.translateResolvedUri(importingLibrary, resolvedUri, node); 449 compiler.translateResolvedUri(importingLibrary, resolvedUri, node);
423 if (readableUri == null) return null; 450 if (readableUri == null) return new Future.value();
424 LibraryElement library; 451 LibraryElement library;
425 if (canonicalUri != null) { 452 if (canonicalUri != null) {
426 library = compiler.libraries[canonicalUri.toString()]; 453 library = compiler.libraries[canonicalUri.toString()];
427 } 454 }
428 if (library == null) { 455 if (library != null) {
429 Script script = compiler.readScript(readableUri, node); 456 return new Future.value(library);
430 if (script == null) return null;
431
432 library = new LibraryElementX(script, canonicalUri);
433 handler.registerNewLibrary(library);
434 native.maybeEnableNative(compiler, library);
435 if (canonicalUri != null) {
436 compiler.libraries[canonicalUri.toString()] = library;
437 }
438
439 compiler.withCurrentElement(library, () {
440 compiler.scanner.scanLibrary(library);
441 processLibraryTags(handler, library);
442 handler.registerLibraryExports(library);
443 onLibraryLoadedCallbacks.add(
444 () => compiler.onLibraryLoaded(library, resolvedUri));
445 });
446 } 457 }
447 return library; 458 return compiler.readScript(readableUri, importingLibrary, node)
459 .then((Script script) {
460 if (script == null) return null;
461 LibraryElement element = new LibraryElementX(script, canonicalUri);
462 compiler.withCurrentElement(element, () {
463 handler.registerNewLibrary(element);
464 native.maybeEnableNative(compiler, element);
465 if (canonicalUri != null) {
466 compiler.libraries[canonicalUri.toString()] = element;
467 }
468 compiler.scanner.scanLibrary(element);
469 });
470 return processLibraryTags(handler, element).then((_) {
471 compiler.withCurrentElement(element, () {
472 handler.registerLibraryExports(element);
473 onLibraryLoadedCallbacks.add(
474 () => compiler.onLibraryLoaded(element, resolvedUri));
475 });
476 return element;
477 });
478 });
448 } 479 }
449 480
450 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by 481 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by
451 // [LibraryLoaderTask]. 482 // [LibraryLoaderTask].
452 void importLibrary(LibraryElement importingLibrary, 483 void importLibrary(LibraryElement importingLibrary,
453 LibraryElement importedLibrary, 484 LibraryElement importedLibrary,
454 Import tag) { 485 Import tag) {
455 new ImportLink(tag, importedLibrary).importLibrary(compiler, 486 new ImportLink(tag, importedLibrary).importLibrary(compiler,
456 importingLibrary); 487 importingLibrary);
457 } 488 }
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 } 868 }
838 869
839 /** 870 /**
840 * Registers all top-level entities of [library] as starting point for the 871 * Registers all top-level entities of [library] as starting point for the
841 * fixed-point computation of the import/export scopes. 872 * fixed-point computation of the import/export scopes.
842 */ 873 */
843 void registerLibraryExports(LibraryElement library) { 874 void registerLibraryExports(LibraryElement library) {
844 nodeMap[library].registerInitialExports(); 875 nodeMap[library].registerInitialExports();
845 } 876 }
846 } 877 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698