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

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: Updated cf. comments 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);
235 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the
236 // loading of a library cluster.
233 currentHandler = new LibraryDependencyHandler(compiler); 237 currentHandler = new LibraryDependencyHandler(compiler);
234 LibraryElement library = 238 return createLibrary(currentHandler, null, resolvedUri, node,
235 createLibrary(currentHandler, null, resolvedUri, node, canonicalUri); 239 canonicalUri).then((LibraryElement library) {
236 currentHandler.computeExports(); 240 return compiler.withCurrentElement(library, () {
237 currentHandler = null; 241 return measure(() {
238 var workList = onLibraryLoadedCallbacks; 242 currentHandler.computeExports();
239 onLibraryLoadedCallbacks = []; 243 currentHandler = null;
240 workList.forEach((f) => f()); 244 var workList = onLibraryLoadedCallbacks;
241 return library; 245 onLibraryLoadedCallbacks = [];
246 return Future.forEach(workList, (f) => f()).then((_) => library);
247 });
248 });
249 });
242 }); 250 });
243 } 251 }
244 252
245 /** 253 /**
246 * Processes the library tags in [library]. 254 * Processes the library tags in [library].
247 * 255 *
248 * The imported/exported libraries are loaded and processed recursively but 256 * The imported/exported libraries are loaded and processed recursively but
249 * the import/export scopes are not set up. 257 * the import/export scopes are not set up.
250 */ 258 */
251 void processLibraryTags(LibraryDependencyHandler handler, 259 Future processLibraryTags(LibraryDependencyHandler handler,
252 LibraryElement library) { 260 LibraryElement library) {
253 int tagState = TagState.NO_TAG_SEEN; 261 int tagState = TagState.NO_TAG_SEEN;
254 262
255 /** 263 /**
256 * If [value] is less than [tagState] complain and return 264 * If [value] is less than [tagState] complain and return
257 * [tagState]. Otherwise return the new value for [tagState] 265 * [tagState]. Otherwise return the new value for [tagState]
258 * (transition function for state machine). 266 * (transition function for state machine).
259 */ 267 */
260 int checkTag(int value, LibraryTag tag) { 268 int checkTag(int value, LibraryTag tag) {
261 if (tagState > value) { 269 if (tagState > value) {
262 compiler.reportFatalError( 270 compiler.reportFatalError(
263 tag, 271 tag,
264 MessageKind.GENERIC, {'text': 'Error: Out of order.'}); 272 MessageKind.GENERIC, {'text': 'Error: Out of order.'});
265 return tagState; 273 return tagState;
266 } 274 }
267 return TagState.NEXT[value]; 275 return TagState.NEXT[value];
268 } 276 }
269 277
270 bool importsDartCore = false; 278 bool importsDartCore = false;
271 var libraryDependencies = new LinkBuilder<LibraryDependency>(); 279 var libraryDependencies = new LinkBuilder<LibraryDependency>();
272 Uri base = library.entryCompilationUnit.script.uri; 280 Uri base = library.entryCompilationUnit.script.uri;
273 for (LibraryTag tag in library.tags.reverse()) { 281
274 if (tag.isImport) { 282 // TODO(rnystrom): Remove .toList() here if #11523 is fixed.
275 Import import = tag; 283 return Future.forEach(library.tags.reverse().toList(), (LibraryTag tag) {
276 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); 284 compiler.withCurrentElement(library, () {
277 if (import.uri.dartString.slowToString() == 'dart:core') { 285 if (tag.isImport) {
278 importsDartCore = true; 286 Import import = tag;
287 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import);
288 if (import.uri.dartString.slowToString() == 'dart:core') {
289 importsDartCore = true;
290 }
291 libraryDependencies.addLast(import);
292 } else if (tag.isExport) {
293 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag);
294 libraryDependencies.addLast(tag);
295 } else if (tag.isLibraryName) {
296 tagState = checkTag(TagState.LIBRARY, tag);
297 if (library.libraryTag != null) {
298 compiler.cancel("duplicated library declaration", node: tag);
299 } else {
300 library.libraryTag = tag;
301 }
302 checkDuplicatedLibraryName(library);
303 } else if (tag.isPart) {
304 Part part = tag;
305 StringNode uri = part.uri;
306 Uri resolvedUri = base.resolve(uri.dartString.slowToString());
307 tagState = checkTag(TagState.SOURCE, part);
308 return scanPart(part, resolvedUri, library);
309 } else {
310 compiler.internalError("Unhandled library tag.", node: tag);
279 } 311 }
280 libraryDependencies.addLast(import); 312 });
281 } else if (tag.isExport) { 313 }).then((_) {
282 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag); 314 return compiler.withCurrentElement(library, () {
283 libraryDependencies.addLast(tag); 315 // Apply patch, if any.
284 } else if (tag.isLibraryName) { 316 if (library.isPlatformLibrary) {
285 tagState = checkTag(TagState.LIBRARY, tag); 317 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 } 318 }
291 checkDuplicatedLibraryName(library); 319 });
292 } else if (tag.isPart) { 320 }).then((_) {
293 Part part = tag; 321 return compiler.withCurrentElement(library, () {
294 StringNode uri = part.uri; 322 // Import dart:core if not already imported.
295 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); 323 if (!importsDartCore && !isDartCore(library.canonicalUri)) {
296 tagState = checkTag(TagState.SOURCE, part); 324 return loadCoreLibrary(handler).then((LibraryElement coreLibrary) {
297 scanPart(part, resolvedUri, library); 325 handler.registerDependency(library, null, coreLibrary);
298 } else { 326 });
299 compiler.internalError("Unhandled library tag.", node: tag); 327 }
300 } 328 });
301 } 329 }).then((_) {
302 330 // TODO(rnystrom): Remove .toList() here if #11523 is fixed.
303 // Apply patch, if any. 331 return Future.forEach(libraryDependencies.toLink().toList(), (tag) {
304 if (library.isPlatformLibrary) { 332 return compiler.withCurrentElement(library, () {
305 patchDartLibrary(handler, library, library.canonicalUri.path); 333 return registerLibraryFromTag(handler, library, tag);
306 } 334 });
307 335 });
308 // Import dart:core if not already imported. 336 });
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 } 337 }
317 338
318 void checkDuplicatedLibraryName(LibraryElement library) { 339 void checkDuplicatedLibraryName(LibraryElement library) {
319 LibraryName tag = library.libraryTag; 340 LibraryName tag = library.libraryTag;
320 if (tag != null) { 341 if (tag != null) {
321 String name = library.getLibraryOrScriptName(); 342 String name = library.getLibraryOrScriptName();
322 LibraryElement existing = 343 LibraryElement existing =
323 libraryNames.putIfAbsent(name, () => library); 344 libraryNames.putIfAbsent(name, () => library);
324 if (!identical(existing, library)) { 345 if (!identical(existing, library)) {
325 Uri uri = library.entryCompilationUnit.script.uri; 346 Uri uri = library.entryCompilationUnit.script.uri;
326 compiler.reportMessage( 347 compiler.reportMessage(
327 compiler.spanFromSpannable(tag.name, uri), 348 compiler.spanFromSpannable(tag.name, uri),
328 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), 349 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}),
329 api.Diagnostic.WARNING); 350 api.Diagnostic.WARNING);
330 Uri existingUri = existing.entryCompilationUnit.script.uri; 351 Uri existingUri = existing.entryCompilationUnit.script.uri;
331 compiler.reportMessage( 352 compiler.reportMessage(
332 compiler.spanFromSpannable(existing.libraryTag.name, existingUri), 353 compiler.spanFromSpannable(existing.libraryTag.name, existingUri),
333 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), 354 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}),
334 api.Diagnostic.WARNING); 355 api.Diagnostic.WARNING);
335 } 356 }
336 } 357 }
337 } 358 }
338 359
339 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core"; 360 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core";
340 361
341 /** 362 /**
342 * Lazily loads and returns the [LibraryElement] for the dart:core library. 363 * Lazily loads and returns the [LibraryElement] for the dart:core library.
343 */ 364 */
344 LibraryElement loadCoreLibrary(LibraryDependencyHandler handler) { 365 Future<LibraryElement> loadCoreLibrary(LibraryDependencyHandler handler) {
345 if (compiler.coreLibrary == null) { 366 if (compiler.coreLibrary != null) {
346 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); 367 return new Future.value(compiler.coreLibrary);
347 compiler.coreLibrary
348 = createLibrary(handler, null, coreUri, null, coreUri);
349 } 368 }
350 return compiler.coreLibrary; 369
370 Uri coreUri = new Uri(scheme: 'dart', path: 'core');
371 return createLibrary(handler, null, coreUri, null, coreUri)
372 .then((LibraryElement library) {
373 compiler.coreLibrary = library;
374 return library;
375 });
351 } 376 }
352 377
353 void patchDartLibrary(LibraryDependencyHandler handler, 378 Future patchDartLibrary(LibraryDependencyHandler handler,
354 LibraryElement library, String dartLibraryPath) { 379 LibraryElement library, String dartLibraryPath) {
355 if (library.isPatched) return; 380 if (library.isPatched) return new Future.value();
356 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); 381 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath);
357 if (patchUri != null) { 382 if (patchUri == null) return new Future.value();
358 compiler.patchParser.patchLibrary(handler, patchUri, library); 383
359 } 384 return compiler.patchParser.patchLibrary(handler, patchUri, library);
360 } 385 }
361 386
362 /** 387 /**
363 * Handle a part tag in the scope of [library]. The [resolvedUri] given is 388 * Handle a part tag in the scope of [library]. The [resolvedUri] given is
364 * used as is, any URI resolution should be done beforehand. 389 * used as is, any URI resolution should be done beforehand.
365 */ 390 */
366 void scanPart(Part part, Uri resolvedUri, LibraryElement library) { 391 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) {
367 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); 392 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri);
368 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); 393 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part);
369 if (readableUri == null) return; 394 if (readableUri == null) return new Future.value();
370 Script sourceScript = compiler.readScript(readableUri, part); 395 return compiler.readScript(readableUri, library, part).
371 if (sourceScript == null) return; 396 then((Script sourceScript) {
372 CompilationUnitElement unit = 397 if (sourceScript == null) return;
373 new CompilationUnitElementX(sourceScript, library); 398 CompilationUnitElement unit =
374 compiler.withCurrentElement(unit, () { 399 new CompilationUnitElementX(sourceScript, library);
375 compiler.scanner.scan(unit); 400 compiler.withCurrentElement(unit, () {
376 if (unit.partTag == null) { 401 compiler.scanner.scan(unit);
377 compiler.reportError(unit, MessageKind.MISSING_PART_OF_TAG); 402 if (unit.partTag == null) {
378 } 403 compiler.reportError(unit, MessageKind.MISSING_PART_OF_TAG);
379 }); 404 }
405 });
406 });
380 } 407 }
381 408
382 /** 409 /**
383 * Handle an import/export tag by loading the referenced library and 410 * Handle an import/export tag by loading the referenced library and
384 * registering its dependency in [handler] for the computation of the import/ 411 * registering its dependency in [handler] for the computation of the import/
385 * export scope. 412 * export scope.
386 */ 413 */
387 void registerLibraryFromTag(LibraryDependencyHandler handler, 414 Future registerLibraryFromTag(LibraryDependencyHandler handler,
388 LibraryElement library, 415 LibraryElement library,
389 LibraryDependency tag) { 416 LibraryDependency tag) {
390 Uri base = library.entryCompilationUnit.script.uri; 417 Uri base = library.entryCompilationUnit.script.uri;
391 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString()); 418 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString());
392 LibraryElement loadedLibrary = 419 return createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri)
393 createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri); 420 .then((LibraryElement loadedLibrary) {
394 if (loadedLibrary == null) return; 421 if (loadedLibrary == null) return;
395 handler.registerDependency(library, tag, loadedLibrary); 422 compiler.withCurrentElement(library, () {
423 handler.registerDependency(library, tag, loadedLibrary);
396 424
397 if (!loadedLibrary.hasLibraryName()) { 425 if (!loadedLibrary.hasLibraryName()) {
398 compiler.withCurrentElement(library, () { 426 compiler.reportFatalError(
399 compiler.reportFatalError( 427 tag == null ? null : tag.uri,
400 tag == null ? null : tag.uri, 428 MessageKind.GENERIC,
401 MessageKind.GENERIC, 429 {'text':
402 {'text': 430 'Error: No library name found in '
403 'Error: No library name found in ${loadedLibrary.canonicalUri}.'}); 431 '${loadedLibrary.canonicalUri}.'});
404 }); 432 }
405 } 433 });
434 });
406 } 435 }
407 436
408 /** 437 /**
409 * Create (or reuse) a library element for the library specified by the 438 * Create (or reuse) a library element for the library specified by the
410 * [resolvedUri]. 439 * [resolvedUri].
411 * 440 *
412 * If a new library is created, the [handler] is notified. 441 * If a new library is created, the [handler] is notified.
413 */ 442 */
414 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the 443 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the
415 // canonical uri when [Compiler.scanBuiltinLibrary] is removed. 444 // canonical uri when [Compiler.scanBuiltinLibrary] is removed.
416 LibraryElement createLibrary(LibraryDependencyHandler handler, 445 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler,
417 LibraryElement importingLibrary, 446 LibraryElement importingLibrary,
418 Uri resolvedUri, Node node, Uri canonicalUri) { 447 Uri resolvedUri, Node node, Uri canonicalUri) {
419 // TODO(johnniwinther): Create erroneous library elements for missing 448 // TODO(johnniwinther): Create erroneous library elements for missing
420 // libraries. 449 // libraries.
421 Uri readableUri = 450 Uri readableUri =
422 compiler.translateResolvedUri(importingLibrary, resolvedUri, node); 451 compiler.translateResolvedUri(importingLibrary, resolvedUri, node);
423 if (readableUri == null) return null; 452 if (readableUri == null) return new Future.value();
424 LibraryElement library; 453 LibraryElement library;
425 if (canonicalUri != null) { 454 if (canonicalUri != null) {
426 library = compiler.libraries[canonicalUri.toString()]; 455 library = compiler.libraries[canonicalUri.toString()];
427 } 456 }
428 if (library == null) { 457 if (library != null) {
429 Script script = compiler.readScript(readableUri, node); 458 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 } 459 }
447 return library; 460 return compiler.readScript(readableUri, importingLibrary, node)
461 .then((Script script) {
462 if (script == null) return null;
463 LibraryElement element = new LibraryElementX(script, canonicalUri);
464 compiler.withCurrentElement(element, () {
465 handler.registerNewLibrary(element);
466 native.maybeEnableNative(compiler, element);
467 if (canonicalUri != null) {
468 compiler.libraries[canonicalUri.toString()] = element;
469 }
470 compiler.scanner.scanLibrary(element);
471 });
472 return processLibraryTags(handler, element).then((_) {
473 compiler.withCurrentElement(element, () {
474 handler.registerLibraryExports(element);
475 onLibraryLoadedCallbacks.add(
476 () => compiler.onLibraryLoaded(element, resolvedUri));
477 });
478 return element;
479 });
480 });
448 } 481 }
449 482
450 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by 483 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by
451 // [LibraryLoaderTask]. 484 // [LibraryLoaderTask].
452 void importLibrary(LibraryElement importingLibrary, 485 void importLibrary(LibraryElement importingLibrary,
453 LibraryElement importedLibrary, 486 LibraryElement importedLibrary,
454 Import tag) { 487 Import tag) {
455 new ImportLink(tag, importedLibrary).importLibrary(compiler, 488 new ImportLink(tag, importedLibrary).importLibrary(compiler,
456 importingLibrary); 489 importingLibrary);
457 } 490 }
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 } 870 }
838 871
839 /** 872 /**
840 * Registers all top-level entities of [library] as starting point for the 873 * Registers all top-level entities of [library] as starting point for the
841 * fixed-point computation of the import/export scopes. 874 * fixed-point computation of the import/export scopes.
842 */ 875 */
843 void registerLibraryExports(LibraryElement library) { 876 void registerLibraryExports(LibraryElement library) {
844 nodeMap[library].registerInitialExports(); 877 nodeMap[library].registerInitialExports();
845 } 878 }
846 } 879 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698