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

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

Powered by Google App Engine
This is Rietveld 408576698