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

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

Powered by Google App Engine
This is Rietveld 408576698