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

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: Remove withCurrentElementAsync 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(() {
ahe 2013/08/06 16:29:17 Record current element?
Johnni Winther 2013/08/27 11:05:00 Done.
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
270 if (tag.isImport) { 275 // TODO(rnystrom): Remove .toList() here if #11523 is fixed.
271 Import import = tag; 276 return Future.forEach(library.tags.reverse().toList(), (LibraryTag tag) {
272 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); 277 compiler.withCurrentElement(library, () {
273 if (import.uri.dartString.slowToString() == 'dart:core') { 278 if (tag.isImport) {
274 importsDartCore = true; 279 Import import = tag;
280 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import);
281 if (import.uri.dartString.slowToString() == 'dart:core') {
282 importsDartCore = true;
283 }
284 libraryDependencies.addLast(import);
285 } else if (tag.isExport) {
286 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag);
287 libraryDependencies.addLast(tag);
288 } else if (tag.isLibraryName) {
289 tagState = checkTag(TagState.LIBRARY, tag);
290 if (library.libraryTag != null) {
291 compiler.cancel("duplicated library declaration", node: tag);
292 } else {
293 library.libraryTag = tag;
294 }
295 checkDuplicatedLibraryName(library);
296 } else if (tag.isPart) {
297 Part part = tag;
298 StringNode uri = part.uri;
299 Uri resolvedUri = base.resolve(uri.dartString.slowToString());
300 tagState = checkTag(TagState.SOURCE, part);
301 return scanPart(part, resolvedUri, library);
302 } else {
303 compiler.internalError("Unhandled library tag.", node: tag);
275 } 304 }
276 libraryDependencies.addLast(import); 305 });
277 } else if (tag.isExport) { 306 }).then((_) {
ahe 2013/08/06 16:29:17 Seems like there is a lack of calls to withCurrent
Johnni Winther 2013/08/27 11:05:00 Don't think they are needed but better safe than s
278 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag); 307 // Apply patch, if any.
279 libraryDependencies.addLast(tag); 308 if (library.isPlatformLibrary) {
280 } else if (tag.isLibraryName) { 309 return patchDartLibrary(handler, library, library.canonicalUri.path);
281 tagState = checkTag(TagState.LIBRARY, tag);
282 if (library.libraryTag != null) {
283 compiler.cancel("duplicated library declaration", node: tag);
284 } else {
285 library.libraryTag = tag;
286 }
287 checkDuplicatedLibraryName(library);
288 } else if (tag.isPart) {
289 Part part = tag;
290 StringNode uri = part.uri;
291 Uri resolvedUri = base.resolve(uri.dartString.slowToString());
292 tagState = checkTag(TagState.SOURCE, part);
293 scanPart(part, resolvedUri, library);
294 } else {
295 compiler.internalError("Unhandled library tag.", node: tag);
296 } 310 }
297 } 311 }).then((_) {
298 312 // Import dart:core if not already imported.
299 // Apply patch, if any. 313 if (!importsDartCore && !isDartCore(library.canonicalUri)) {
300 if (library.isPlatformLibrary) { 314 return loadCoreLibrary(handler).then((LibraryElement coreLibrary) {
301 patchDartLibrary(handler, library, library.canonicalUri.path); 315 handler.registerDependency(library, null, coreLibrary);
302 } 316 });
303 317 }
304 // Import dart:core if not already imported. 318 }).then((_) {
305 if (!importsDartCore && !isDartCore(library.canonicalUri)) { 319 // TODO(rnystrom): Remove .toList() here if #11523 is fixed.
306 handler.registerDependency(library, null, loadCoreLibrary(handler)); 320 return Future.forEach(libraryDependencies.toLink().toList(), (tag) {
307 } 321 return registerLibraryFromTag(handler, library, tag);
308 322 });
309 for (LibraryDependency tag in libraryDependencies.toLink()) { 323 });
310 registerLibraryFromTag(handler, library, tag);
311 }
312 } 324 }
313 325
314 void checkDuplicatedLibraryName(LibraryElement library) { 326 void checkDuplicatedLibraryName(LibraryElement library) {
315 LibraryName tag = library.libraryTag; 327 LibraryName tag = library.libraryTag;
316 if (tag != null) { 328 if (tag != null) {
317 String name = library.getLibraryOrScriptName(); 329 String name = library.getLibraryOrScriptName();
318 LibraryElement existing = 330 LibraryElement existing =
319 libraryNames.putIfAbsent(name, () => library); 331 libraryNames.putIfAbsent(name, () => library);
320 if (!identical(existing, library)) { 332 if (!identical(existing, library)) {
321 Uri uri = library.entryCompilationUnit.script.uri; 333 Uri uri = library.entryCompilationUnit.script.uri;
322 compiler.reportMessage( 334 compiler.reportMessage(
323 compiler.spanFromSpannable(tag.name, uri), 335 compiler.spanFromSpannable(tag.name, uri),
324 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), 336 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}),
325 api.Diagnostic.WARNING); 337 api.Diagnostic.WARNING);
326 Uri existingUri = existing.entryCompilationUnit.script.uri; 338 Uri existingUri = existing.entryCompilationUnit.script.uri;
327 compiler.reportMessage( 339 compiler.reportMessage(
328 compiler.spanFromSpannable(existing.libraryTag.name, existingUri), 340 compiler.spanFromSpannable(existing.libraryTag.name, existingUri),
329 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), 341 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}),
330 api.Diagnostic.WARNING); 342 api.Diagnostic.WARNING);
331 } 343 }
332 } 344 }
333 } 345 }
334 346
335 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core"; 347 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core";
336 348
337 /** 349 /**
338 * Lazily loads and returns the [LibraryElement] for the dart:core library. 350 * Lazily loads and returns the [LibraryElement] for the dart:core library.
339 */ 351 */
340 LibraryElement loadCoreLibrary(LibraryDependencyHandler handler) { 352 Future<LibraryElement> loadCoreLibrary(LibraryDependencyHandler handler) {
341 if (compiler.coreLibrary == null) { 353 if (compiler.coreLibrary != null) {
342 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); 354 return new Future.value(compiler.coreLibrary);
343 compiler.coreLibrary
344 = createLibrary(handler, null, coreUri, null, coreUri);
345 } 355 }
346 return compiler.coreLibrary; 356
357 Uri coreUri = new Uri(scheme: 'dart', path: 'core');
358 return createLibrary(handler, null, coreUri, null, coreUri)
359 .then((LibraryElement library) {
360 compiler.coreLibrary = library;
361 return library;
362 });
347 } 363 }
348 364
349 void patchDartLibrary(LibraryDependencyHandler handler, 365 Future patchDartLibrary(LibraryDependencyHandler handler,
350 LibraryElement library, String dartLibraryPath) { 366 LibraryElement library, String dartLibraryPath) {
351 if (library.isPatched) return; 367 if (library.isPatched) return new Future.value();
352 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); 368 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath);
353 if (patchUri != null) { 369 if (patchUri == null) return new Future.value();
354 compiler.patchParser.patchLibrary(handler, patchUri, library); 370
355 } 371 return compiler.patchParser.patchLibrary(handler, patchUri, library);
356 } 372 }
357 373
358 /** 374 /**
359 * Handle a part tag in the scope of [library]. The [resolvedUri] given is 375 * Handle a part tag in the scope of [library]. The [resolvedUri] given is
360 * used as is, any URI resolution should be done beforehand. 376 * used as is, any URI resolution should be done beforehand.
361 */ 377 */
362 void scanPart(Part part, Uri resolvedUri, LibraryElement library) { 378 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) {
363 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); 379 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri);
364 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); 380 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part);
365 Script sourceScript = compiler.readScript(readableUri, part); 381 return compiler.readScript(readableUri, library, part).
366 CompilationUnitElement unit = 382 then((Script sourceScript) {
367 new CompilationUnitElementX(sourceScript, library); 383 CompilationUnitElement unit =
368 compiler.withCurrentElement(unit, () { 384 new CompilationUnitElementX(sourceScript, library);
369 compiler.scanner.scan(unit); 385 compiler.withCurrentElement(unit, () {
370 if (unit.partTag == null) { 386 compiler.scanner.scan(unit);
371 bool wasDiagnosticEmitted = false; 387 if (unit.partTag == null) {
372 compiler.withCurrentElement(library, () { 388 bool wasDiagnosticEmitted = false;
373 wasDiagnosticEmitted = 389 compiler.withCurrentElement(library, () {
374 compiler.onDeprecatedFeature(part, 'missing part-of tag'); 390 wasDiagnosticEmitted =
391 compiler.onDeprecatedFeature(part, 'missing part-of tag');
392 });
393 if (wasDiagnosticEmitted) {
394 compiler.reportMessage(
395 compiler.spanFromElement(unit),
396 MessageKind.MISSING_PART_OF_TAG.error(),
397 api.Diagnostic.INFO);
398 }
399 }
400 });
375 }); 401 });
376 if (wasDiagnosticEmitted) {
377 compiler.reportMessage(
378 compiler.spanFromElement(unit),
379 MessageKind.MISSING_PART_OF_TAG.error(),
380 api.Diagnostic.INFO);
381 }
382 }
383 });
384 } 402 }
385 403
386 /** 404 /**
387 * Handle an import/export tag by loading the referenced library and 405 * Handle an import/export tag by loading the referenced library and
388 * registering its dependency in [handler] for the computation of the import/ 406 * registering its dependency in [handler] for the computation of the import/
389 * export scope. 407 * export scope.
390 */ 408 */
391 void registerLibraryFromTag(LibraryDependencyHandler handler, 409 Future registerLibraryFromTag(LibraryDependencyHandler handler,
392 LibraryElement library, 410 LibraryElement library,
393 LibraryDependency tag) { 411 LibraryDependency tag) {
394 Uri base = library.entryCompilationUnit.script.uri; 412 Uri base = library.entryCompilationUnit.script.uri;
395 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString()); 413 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString());
396 LibraryElement loadedLibrary = 414 return createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri)
397 createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri); 415 .then((LibraryElement loadedLibrary) {
ahe 2013/08/06 16:29:17 withCurrentElement?
Johnni Winther 2013/08/27 11:05:00 Done.
398 handler.registerDependency(library, tag, loadedLibrary); 416 handler.registerDependency(library, tag, loadedLibrary);
399 417
400 if (!loadedLibrary.hasLibraryName()) { 418 if (!loadedLibrary.hasLibraryName()) {
401 compiler.withCurrentElement(library, () { 419 compiler.withCurrentElement(library, () {
402 compiler.reportFatalError( 420 compiler.reportFatalError(
403 tag == null ? null : tag.uri, 421 tag == null ? null : tag.uri,
404 MessageKind.GENERIC, 422 MessageKind.GENERIC,
405 {'text': 423 {'text':
406 'Error: No library name found in ${loadedLibrary.canonicalUri}.'}); 424 'Error: No library name found in '
407 }); 425 '${loadedLibrary.canonicalUri}.'});
408 } 426 });
427 }
428 });
409 } 429 }
410 430
411 /** 431 /**
412 * Create (or reuse) a library element for the library specified by the 432 * Create (or reuse) a library element for the library specified by the
413 * [resolvedUri]. 433 * [resolvedUri].
414 * 434 *
415 * If a new library is created, the [handler] is notified. 435 * If a new library is created, the [handler] is notified.
416 */ 436 */
417 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the 437 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the
418 // canonical uri when [Compiler.scanBuiltinLibrary] is removed. 438 // canonical uri when [Compiler.scanBuiltinLibrary] is removed.
419 LibraryElement createLibrary(LibraryDependencyHandler handler, 439 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler,
420 LibraryElement importingLibrary, 440 LibraryElement importingLibrary,
421 Uri resolvedUri, Node node, Uri canonicalUri) { 441 Uri resolvedUri, Node node, Uri canonicalUri) {
422 bool newLibrary = false;
423 Uri readableUri = 442 Uri readableUri =
424 compiler.translateResolvedUri(importingLibrary, resolvedUri, node); 443 compiler.translateResolvedUri(importingLibrary, resolvedUri, node);
425 if (readableUri == null) return null; 444 if (readableUri == null) return null;
426 LibraryElement createLibrary() { 445
427 newLibrary = true; 446 if (canonicalUri != null) {
428 Script script = compiler.readScript(readableUri, node); 447 LibraryElement library = compiler.libraries[canonicalUri.toString()];
429 LibraryElement element = new LibraryElementX(script, canonicalUri); 448 if (library != null) {
430 handler.registerNewLibrary(element); 449 return new Future.value(library);
431 native.maybeEnableNative(compiler, element); 450 }
432 return element;
433 } 451 }
434 LibraryElement library; 452
435 if (canonicalUri == null) { 453 return compiler.readScript(readableUri, importingLibrary, node).
ahe 2013/08/06 16:29:17 Period goes on next line according to style guide
Johnni Winther 2013/08/27 11:05:00 Done.
436 library = createLibrary(); 454 then((Script script) {
437 } else { 455 LibraryElement element = new LibraryElementX(script, canonicalUri);
438 library = compiler.libraries.putIfAbsent(canonicalUri.toString(), 456 handler.registerNewLibrary(element);
439 createLibrary); 457 native.maybeEnableNative(compiler, element);
440 } 458 compiler.libraries[canonicalUri.toString()] = element;
441 if (newLibrary) { 459 compiler.withCurrentElement(element, () {
ahe 2013/08/06 16:29:17 Would it make sense to move lines 456-458 into thi
Johnni Winther 2013/08/27 11:05:00 Done.
442 compiler.withCurrentElement(library, () { 460 compiler.scanner.scanLibrary(element);
443 compiler.scanner.scanLibrary(library); 461 });
444 processLibraryTags(handler, library); 462 return processLibraryTags(handler, element).then((_) {
445 handler.registerLibraryExports(library); 463 compiler.withCurrentElement(element, () {
446 compiler.onLibraryScanned(library, resolvedUri); 464 handler.registerLibraryExports(element);
447 }); 465 compiler.onLibraryScanned(element, resolvedUri);
448 } 466 });
449 return library; 467 return element;
468 });
469 });
450 } 470 }
451 471
452 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by 472 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by
453 // [LibraryLoaderTask]. 473 // [LibraryLoaderTask].
454 void importLibrary(LibraryElement importingLibrary, 474 void importLibrary(LibraryElement importingLibrary,
455 LibraryElement importedLibrary, 475 LibraryElement importedLibrary,
456 Import tag) { 476 Import tag) {
457 new ImportLink(tag, importedLibrary).importLibrary(compiler, 477 new ImportLink(tag, importedLibrary).importLibrary(compiler,
458 importingLibrary); 478 importingLibrary);
459 } 479 }
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 } 859 }
840 860
841 /** 861 /**
842 * Registers all top-level entities of [library] as starting point for the 862 * Registers all top-level entities of [library] as starting point for the
843 * fixed-point computation of the import/export scopes. 863 * fixed-point computation of the import/export scopes.
844 */ 864 */
845 void registerLibraryExports(LibraryElement library) { 865 void registerLibraryExports(LibraryElement library) {
846 nodeMap[library].registerInitialExports(); 866 nodeMap[library].registerInitialExports();
847 } 867 }
848 } 868 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698