| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library deferred_load; | 5 library deferred_load; |
| 6 | 6 |
| 7 import 'dart2jslib.dart' show | 7 import 'dart2jslib.dart' show |
| 8 Backend, | 8 Backend, |
| 9 Compiler, | 9 Compiler, |
| 10 CompilerTask, | 10 CompilerTask, |
| 11 Constant, | 11 Constant, |
| 12 ConstructedConstant, | 12 ConstructedConstant, |
| 13 LibraryLoaderTask, |
| 13 MessageKind, | 14 MessageKind, |
| 14 StringConstant, | 15 StringConstant, |
| 15 invariant, | 16 invariant; |
| 16 Backend; | |
| 17 | 17 |
| 18 import 'dart_backend/dart_backend.dart' show | 18 import 'dart_backend/dart_backend.dart' show |
| 19 DartBackend; | 19 DartBackend; |
| 20 | 20 |
| 21 import 'js_backend/js_backend.dart' show | 21 import 'js_backend/js_backend.dart' show |
| 22 JavaScriptBackend; | 22 JavaScriptBackend; |
| 23 | 23 |
| 24 import 'elements/elements.dart' show | 24 import 'elements/elements.dart' show |
| 25 Element, | 25 Element, |
| 26 ClassElement, | 26 ClassElement, |
| 27 ElementKind, | 27 ElementKind, |
| 28 Elements, | 28 Elements, |
| 29 FunctionElement, | 29 FunctionElement, |
| 30 LibraryElement, | 30 LibraryElement, |
| 31 MetadataAnnotation, | 31 MetadataAnnotation, |
| 32 ScopeContainerElement, | 32 ScopeContainerElement, |
| 33 PrefixElement, | 33 PrefixElement, |
| 34 ClosureContainer, | 34 ClosureContainer, |
| 35 VoidElement; | 35 VoidElement, |
| 36 TypedefElement; |
| 36 | 37 |
| 37 import 'util/util.dart' show | 38 import 'util/util.dart' show |
| 38 Link; | 39 Link; |
| 39 | 40 |
| 40 import 'util/setlet.dart' show | 41 import 'util/setlet.dart' show |
| 41 Setlet; | 42 Setlet; |
| 42 | 43 |
| 43 import 'tree/tree.dart' show | 44 import 'tree/tree.dart' show |
| 44 LibraryTag, | 45 LibraryTag, |
| 45 Node, | 46 Node, |
| 46 NewExpression, | 47 NewExpression, |
| 47 Import, | 48 Import, |
| 48 LiteralString, | 49 LiteralString, |
| 49 LiteralDartString; | 50 LiteralDartString; |
| 50 | 51 |
| 51 import 'tree/tree.dart' as ast; | 52 import 'tree/tree.dart' as ast; |
| 52 | 53 |
| 53 import 'resolution/resolution.dart' show | 54 import 'resolution/resolution.dart' show |
| 54 TreeElements; | 55 TreeElements, |
| 55 | 56 AnalyzableElement; |
| 56 import 'mirrors_used.dart' show | |
| 57 MirrorUsageAnalyzer, | |
| 58 MirrorUsageAnalyzerTask, | |
| 59 MirrorUsage; | |
| 60 | 57 |
| 61 /// A "hunk" of the program that will be loaded whenever one of its [imports] | 58 /// A "hunk" of the program that will be loaded whenever one of its [imports] |
| 62 /// are loaded. | 59 /// are loaded. |
| 63 /// | 60 /// |
| 64 /// Elements that are only used in one deferred import, is in an OutputUnit with | 61 /// Elements that are only used in one deferred import, is in an OutputUnit with |
| 65 /// the deferred import as single element in the [imports] set. | 62 /// the deferred import as single element in the [imports] set. |
| 66 /// | 63 /// |
| 67 /// Whenever a deferred Element is shared between several deferred imports it is | 64 /// Whenever a deferred Element is shared between several deferred imports it is |
| 68 /// in an output unit with those imports in the [imports] Set. | 65 /// in an output unit with those imports in the [imports] Set. |
| 69 /// | 66 /// |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 elements.add(constant.type.element); | 292 elements.add(constant.type.element); |
| 296 } | 293 } |
| 297 constant.getDependencies().forEach(addConstants); | 294 constant.getDependencies().forEach(addConstants); |
| 298 } | 295 } |
| 299 | 296 |
| 300 /// Collects all direct dependencies of [element]. | 297 /// Collects all direct dependencies of [element]. |
| 301 /// | 298 /// |
| 302 /// The collected dependent elements and constants are are added to | 299 /// The collected dependent elements and constants are are added to |
| 303 /// [elements] and [constants] respectively. | 300 /// [elements] and [constants] respectively. |
| 304 void collectDependencies(Element element) { | 301 void collectDependencies(Element element) { |
| 305 TreeElements treeElements = element.isTypedef | 302 TreeElements treeElements = element is TypedefElement |
| 306 ? element.treeElements | 303 ? element.treeElements |
| 307 : compiler.enqueuer.resolution.getCachedElements(element); | 304 : compiler.enqueuer.resolution.getCachedElements(element); |
| 308 | 305 |
| 309 // TODO(sigurdm): We want to be more specific about this - need a better | 306 // TODO(sigurdm): We want to be more specific about this - need a better |
| 310 // way to query "liveness". | 307 // way to query "liveness". |
| 311 if (treeElements == null) return; | 308 if (treeElements == null) return; |
| 312 | 309 |
| 313 for (Element dependency in treeElements.allElements) { | 310 for (Element dependency in treeElements.allElements) { |
| 314 if (Elements.isLocal(dependency) && !dependency.isFunction) continue; | 311 if (Elements.isLocal(dependency) && !dependency.isFunction) continue; |
| 315 if (dependency.isErroneous) continue; | 312 if (dependency.isErroneous) continue; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 } else { | 422 } else { |
| 426 _mapDependencies(dependency, import); | 423 _mapDependencies(dependency, import); |
| 427 } | 424 } |
| 428 } | 425 } |
| 429 } | 426 } |
| 430 | 427 |
| 431 /// Adds extra dependencies coming from mirror usage. | 428 /// Adds extra dependencies coming from mirror usage. |
| 432 /// | 429 /// |
| 433 /// The elements are added with [_mapDependencies]. | 430 /// The elements are added with [_mapDependencies]. |
| 434 void _addMirrorElements() { | 431 void _addMirrorElements() { |
| 435 MirrorUsageAnalyzerTask mirrorTask = compiler.mirrorUsageAnalyzerTask; | 432 void mapDependenciesIfResolved(Element element, Import deferredImport) { |
| 436 // For each import we record all mirrors-used elements from all the | 433 // If an element is the target of a MirrorsUsed annotation but never used |
| 437 // libraries reached directly from that import. | 434 // It will not be resolved, and we should not call isNeededForReflection. |
| 435 // TODO(sigurdm): Unresolved elements should just answer false when |
| 436 // asked isNeededForReflection. Instead an internal error is triggered. |
| 437 // So we have to filter them out here. |
| 438 if (element is AnalyzableElement && !element.hasTreeElements) return; |
| 439 if (compiler.backend.isNeededForReflection(element)) { |
| 440 _mapDependencies(element, deferredImport); |
| 441 } |
| 442 } |
| 443 |
| 444 Set<LibraryElement> seenLibraries = new Set<LibraryElement>(); |
| 445 |
| 446 // For each deferred import we analyze all elements reachable from the |
| 447 // imported library through non-deferred imports. |
| 448 handleLibrary(LibraryElement library, Import deferredImport) { |
| 449 seenLibraries.add(library); |
| 450 |
| 451 library.forEachLocalMember((Element element) { |
| 452 mapDependenciesIfResolved(element, deferredImport); |
| 453 }); |
| 454 if (library.isPatched) { |
| 455 library.implementation.forEachLocalMember((Element element) { |
| 456 mapDependenciesIfResolved(element, deferredImport); |
| 457 }); |
| 458 } |
| 459 |
| 460 for (MetadataAnnotation metadata in library.metadata) { |
| 461 Constant constant = |
| 462 backend.constants.getConstantForMetadata(metadata); |
| 463 if (constant != null) { |
| 464 _mapDependencies(constant.computeType(compiler).element, |
| 465 deferredImport); |
| 466 } |
| 467 } |
| 468 for (LibraryTag tag in library.tags) { |
| 469 for (MetadataAnnotation metadata in tag.metadata) { |
| 470 Constant constant = |
| 471 backend.constants.getConstantForMetadata(metadata); |
| 472 if (constant != null) { |
| 473 _mapDependencies(constant.computeType(compiler).element, |
| 474 deferredImport); |
| 475 } |
| 476 } |
| 477 } |
| 478 } |
| 479 |
| 438 for (Import deferredImport in _allDeferredImports.keys) { | 480 for (Import deferredImport in _allDeferredImports.keys) { |
| 439 LibraryElement deferredLibrary = _allDeferredImports[deferredImport]; | 481 LibraryElement deferredLibrary = _allDeferredImports[deferredImport]; |
| 440 for (LibraryElement library in | 482 for (LibraryElement library in |
| 441 _nonDeferredReachableLibraries(deferredLibrary)) { | 483 _nonDeferredReachableLibraries(deferredLibrary)) { |
| 442 // TODO(sigurdm): The metadata should go to the right output unit. | 484 handleLibrary(library, deferredImport); |
| 443 // For now they all go to the main output unit. | 485 } |
| 444 for (MetadataAnnotation metadata in library.metadata) { | 486 } |
| 445 Constant constant = | |
| 446 backend.constants.getConstantForMetadata(metadata); | |
| 447 if (constant != null) { | |
| 448 _mapDependencies(constant.computeType(compiler).element, | |
| 449 _fakeMainImport); | |
| 450 } | |
| 451 } | |
| 452 for (LibraryTag tag in library.tags) { | |
| 453 for (MetadataAnnotation metadata in tag.metadata) { | |
| 454 Constant constant = | |
| 455 backend.constants.getConstantForMetadata(metadata); | |
| 456 if (constant != null) { | |
| 457 _mapDependencies(constant.computeType(compiler).element, | |
| 458 _fakeMainImport); | |
| 459 } | |
| 460 } | |
| 461 } | |
| 462 | 487 |
| 463 if (mirrorTask.librariesWithUsage.contains(library)) { | 488 // A number of libraries are never imported explicitly - they belong to the |
| 464 | 489 // main output unit. |
| 465 Map<LibraryElement, List<MirrorUsage>> mirrorsResult = | 490 LibraryLoaderTask loader = compiler.libraryLoader; |
| 466 mirrorTask.analyzer.collectMirrorsUsedAnnotation(); | 491 for (LibraryElement library in loader.libraryNames.values) { |
| 467 | 492 if (!seenLibraries.contains(library)) { |
| 468 // If there is a MirrorsUsed annotation we add only the needed | 493 handleLibrary(library, _fakeMainImport); |
| 469 // things to the output units for the library. | |
| 470 List<MirrorUsage> mirrorUsages = mirrorsResult[library]; | |
| 471 if (mirrorUsages == null) continue; | |
| 472 | |
| 473 void mapDependenciesIfResolved(Element element) { | |
| 474 // If there is a target for this class, but no use of mirrors the | |
| 475 // class will not be resolved. We just skip it. | |
| 476 if (element is ClassElement &&!element.isResolved) { | |
| 477 return; | |
| 478 } | |
| 479 _mapDependencies(element, deferredImport); | |
| 480 } | |
| 481 | |
| 482 for (MirrorUsage usage in mirrorUsages) { | |
| 483 if (usage.targets != null) { | |
| 484 for (Element dependency in usage.targets) { | |
| 485 if (dependency.isLibrary) { | |
| 486 LibraryElement library = dependency; | |
| 487 library.forEachLocalMember(mapDependenciesIfResolved); | |
| 488 } else { | |
| 489 mapDependenciesIfResolved(dependency); | |
| 490 } | |
| 491 } | |
| 492 } | |
| 493 if (usage.metaTargets != null) { | |
| 494 for (Element dependency in usage.metaTargets) { | |
| 495 _mapDependencies(dependency, deferredImport); | |
| 496 } | |
| 497 } | |
| 498 } | |
| 499 } else { | |
| 500 // If there is no MirrorsUsed annotation we add _everything_ to | |
| 501 // the output units for the library. | |
| 502 | |
| 503 // TODO(sigurdm): This is too expensive. | |
| 504 // Plan: If mirrors are used without MirrorsUsed, create an | |
| 505 // "EverythingElse" library that contains all elements that are | |
| 506 // not referred by main or deferred libraries that don't contain | |
| 507 // mirrors (without MirrorsUsed). | |
| 508 // | |
| 509 // So basically we want: | |
| 510 // mainImport | |
| 511 // deferredA | |
| 512 // deferredB | |
| 513 // deferredCwithMirrorsUsed | |
| 514 // deferredEverythingElse | |
| 515 // | |
| 516 // Where deferredEverythingElse will be loaded for *all* libraries | |
| 517 // that contain a mirror usage without MirrorsUsed. | |
| 518 // When loading the deferredEverythingElse also load all other | |
| 519 // deferred libraries at the same time. | |
| 520 bool usesMirrors = false; | |
| 521 for (LibraryTag tag in library.tags) { | |
| 522 if (tag is! Import) continue; | |
| 523 if (library.getLibraryFromTag(tag) == compiler.mirrorsLibrary) { | |
| 524 usesMirrors = true; | |
| 525 break; | |
| 526 } | |
| 527 } | |
| 528 if (usesMirrors) { | |
| 529 // Add all resolved elements to the output unit. | |
| 530 for (Element element in | |
| 531 compiler.enqueuer.resolution.resolvedElements.keys) { | |
| 532 _mapDependencies(element, deferredImport); | |
| 533 } | |
| 534 for (Element element in | |
| 535 compiler.mirrorDependencies.otherDependencies) { | |
| 536 _mapDependencies(element, deferredImport); | |
| 537 } | |
| 538 } | |
| 539 } | |
| 540 } | 494 } |
| 541 } | 495 } |
| 542 } | 496 } |
| 543 | 497 |
| 544 /// Computes a unique string for the name field for each outputUnit. | 498 /// Computes a unique string for the name field for each outputUnit. |
| 545 /// | 499 /// |
| 546 /// Also sets up the [hunksToLoad] mapping. | 500 /// Also sets up the [hunksToLoad] mapping. |
| 547 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) { | 501 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) { |
| 548 Set<String> usedImportNames = new Set<String>(); | 502 Set<String> usedImportNames = new Set<String>(); |
| 549 | 503 |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 Element maybePrefix = elements[identifier]; | 780 Element maybePrefix = elements[identifier]; |
| 827 if (maybePrefix != null && maybePrefix.isPrefix) { | 781 if (maybePrefix != null && maybePrefix.isPrefix) { |
| 828 PrefixElement prefixElement = maybePrefix; | 782 PrefixElement prefixElement = maybePrefix; |
| 829 if (prefixElement.isDeferred) { | 783 if (prefixElement.isDeferred) { |
| 830 return prefixElement; | 784 return prefixElement; |
| 831 } | 785 } |
| 832 } | 786 } |
| 833 return null; | 787 return null; |
| 834 } | 788 } |
| 835 } | 789 } |
| OLD | NEW |