Chromium Code Reviews| 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, |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 46 NewExpression, | 46 NewExpression, |
| 47 Import, | 47 Import, |
| 48 LiteralString, | 48 LiteralString, |
| 49 LiteralDartString; | 49 LiteralDartString; |
| 50 | 50 |
| 51 import 'tree/tree.dart' as ast; | 51 import 'tree/tree.dart' as ast; |
| 52 | 52 |
| 53 import 'resolution/resolution.dart' show | 53 import 'resolution/resolution.dart' show |
| 54 TreeElements; | 54 TreeElements; |
| 55 | 55 |
| 56 import 'mirrors_used.dart' show | |
| 57 MirrorUsageAnalyzer, | |
| 58 MirrorUsageAnalyzerTask, | |
| 59 MirrorUsage; | |
| 60 | |
| 61 /// A "hunk" of the program that will be loaded whenever one of its [imports] | 56 /// A "hunk" of the program that will be loaded whenever one of its [imports] |
| 62 /// are loaded. | 57 /// are loaded. |
| 63 /// | 58 /// |
| 64 /// Elements that are only used in one deferred import, is in an OutputUnit with | 59 /// 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. | 60 /// the deferred import as single element in the [imports] set. |
| 66 /// | 61 /// |
| 67 /// Whenever a deferred Element is shared between several deferred imports it is | 62 /// Whenever a deferred Element is shared between several deferred imports it is |
| 68 /// in an output unit with those imports in the [imports] Set. | 63 /// in an output unit with those imports in the [imports] Set. |
| 69 /// | 64 /// |
| 70 /// OutputUnits are equal if their [imports] are equal. | 65 /// OutputUnits are equal if their [imports] are equal. |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 elements.add(constant.type.element); | 290 elements.add(constant.type.element); |
| 296 } | 291 } |
| 297 constant.getDependencies().forEach(addConstants); | 292 constant.getDependencies().forEach(addConstants); |
| 298 } | 293 } |
| 299 | 294 |
| 300 /// Collects all direct dependencies of [element]. | 295 /// Collects all direct dependencies of [element]. |
| 301 /// | 296 /// |
| 302 /// The collected dependent elements and constants are are added to | 297 /// The collected dependent elements and constants are are added to |
| 303 /// [elements] and [constants] respectively. | 298 /// [elements] and [constants] respectively. |
| 304 void collectDependencies(Element element) { | 299 void collectDependencies(Element element) { |
| 305 TreeElements treeElements = element.isTypedef | 300 TreeElements treeElements = |
| 306 ? element.treeElements | 301 compiler.enqueuer.resolution.getCachedElements(element); |
|
sigurdm
2014/05/09 11:27:05
.treeElements is not always present on a TypedefEl
karlklose
2014/05/12 06:53:12
Please file a bug and add a TODO.
sigurdm
2014/05/12 12:10:35
This is not a problem after patch set 2 - because
| |
| 307 : compiler.enqueuer.resolution.getCachedElements(element); | |
| 308 | 302 |
| 309 // TODO(sigurdm): We want to be more specific about this - need a better | 303 // TODO(sigurdm): We want to be more specific about this - need a better |
| 310 // way to query "liveness". | 304 // way to query "liveness". |
| 311 if (treeElements == null) return; | 305 if (treeElements == null) return; |
| 312 | 306 |
| 313 for (Element dependency in treeElements.allElements) { | 307 for (Element dependency in treeElements.allElements) { |
| 314 if (Elements.isLocal(dependency) && !dependency.isFunction) continue; | 308 if (Elements.isLocal(dependency) && !dependency.isFunction) continue; |
| 315 if (dependency.isErroneous) continue; | 309 if (dependency.isErroneous) continue; |
| 316 if (dependency.isStatement) continue; | 310 if (dependency.isStatement) continue; |
| 317 if (dependency.isTypeVariable) continue; | 311 if (dependency.isTypeVariable) continue; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 } else { | 419 } else { |
| 426 _mapDependencies(dependency, import); | 420 _mapDependencies(dependency, import); |
| 427 } | 421 } |
| 428 } | 422 } |
| 429 } | 423 } |
| 430 | 424 |
| 431 /// Adds extra dependencies coming from mirror usage. | 425 /// Adds extra dependencies coming from mirror usage. |
| 432 /// | 426 /// |
| 433 /// The elements are added with [_mapDependencies]. | 427 /// The elements are added with [_mapDependencies]. |
| 434 void _addMirrorElements() { | 428 void _addMirrorElements() { |
| 435 MirrorUsageAnalyzerTask mirrorTask = compiler.mirrorUsageAnalyzerTask; | 429 void mapDependenciesIfResolved(Element element, Import deferredImport) { |
| 436 // For each import we record all mirrors-used elements from all the | 430 // If there is a target for this class, but no use of mirrors the |
|
karlklose
2014/05/12 06:53:12
What is a 'target'?
When does it happen, that an
sigurdm
2014/05/12 12:10:35
Done.
| |
| 437 // libraries reached directly from that import. | 431 // class will not be resolved. We just skip it. |
| 432 if (element is ClassElement &&!element.isResolved) return; | |
|
karlklose
2014/05/12 06:53:12
Missing space before '!element'.
sigurdm
2014/05/12 12:10:35
Done.
| |
| 433 _mapDependencies(element, deferredImport); | |
| 434 } | |
| 435 | |
| 436 Set<LibraryElement> seenLibraries = new Set<LibraryElement>(); | |
| 437 | |
| 438 // For each deferred import we analyze all elements reachable from the | |
| 439 // imported library through non-deferred imports. | |
| 440 handleLibrary(LibraryElement library, Import deferredImport) { | |
| 441 seenLibraries.add(library); | |
| 442 | |
| 443 library.forEachLocalMember((Element element) { | |
| 444 if (compiler.backend.isNeededForReflection(element)) { | |
| 445 mapDependenciesIfResolved(element, deferredImport); | |
| 446 } | |
| 447 }); | |
| 448 | |
| 449 for (MetadataAnnotation metadata in library.metadata) { | |
| 450 Constant constant = | |
| 451 backend.constants.getConstantForMetadata(metadata); | |
| 452 if (constant != null) { | |
| 453 _mapDependencies(constant.computeType(compiler).element, | |
| 454 deferredImport); | |
| 455 } | |
| 456 } | |
| 457 for (LibraryTag tag in library.tags) { | |
| 458 for (MetadataAnnotation metadata in tag.metadata) { | |
| 459 Constant constant = | |
| 460 backend.constants.getConstantForMetadata(metadata); | |
| 461 if (constant != null) { | |
| 462 _mapDependencies(constant.computeType(compiler).element, | |
| 463 deferredImport); | |
| 464 } | |
| 465 } | |
| 466 } | |
| 467 } | |
| 468 | |
| 438 for (Import deferredImport in _allDeferredImports.keys) { | 469 for (Import deferredImport in _allDeferredImports.keys) { |
| 439 LibraryElement deferredLibrary = _allDeferredImports[deferredImport]; | 470 LibraryElement deferredLibrary = _allDeferredImports[deferredImport]; |
| 440 for (LibraryElement library in | 471 for (LibraryElement library in |
| 441 _nonDeferredReachableLibraries(deferredLibrary)) { | 472 _nonDeferredReachableLibraries(deferredLibrary)) { |
| 442 // TODO(sigurdm): The metadata should go to the right output unit. | 473 handleLibrary(library, deferredImport); |
| 443 // For now they all go to the main output unit. | 474 } |
| 444 for (MetadataAnnotation metadata in library.metadata) { | 475 } |
| 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 | 476 |
| 463 if (mirrorTask.librariesWithUsage.contains(library)) { | 477 // A number of libraries are never imported explicitly - they belong to the |
| 464 | 478 // main output unit. |
| 465 Map<LibraryElement, List<MirrorUsage>> mirrorsResult = | 479 LibraryLoaderTask loader = compiler.libraryLoader; |
| 466 mirrorTask.analyzer.collectMirrorsUsedAnnotation(); | 480 for (LibraryElement library in loader.libraryNames.values) { |
| 467 | 481 if (!seenLibraries.contains(library)) { |
| 468 // If there is a MirrorsUsed annotation we add only the needed | 482 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 } | 483 } |
| 541 } | 484 } |
| 542 } | 485 } |
| 543 | 486 |
| 544 /// Computes a unique string for the name field for each outputUnit. | 487 /// Computes a unique string for the name field for each outputUnit. |
| 545 /// | 488 /// |
| 546 /// Also sets up the [hunksToLoad] mapping. | 489 /// Also sets up the [hunksToLoad] mapping. |
| 547 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) { | 490 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) { |
| 548 Set<String> usedImportNames = new Set<String>(); | 491 Set<String> usedImportNames = new Set<String>(); |
| 549 | 492 |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 826 Element maybePrefix = elements[identifier]; | 769 Element maybePrefix = elements[identifier]; |
| 827 if (maybePrefix != null && maybePrefix.isPrefix) { | 770 if (maybePrefix != null && maybePrefix.isPrefix) { |
| 828 PrefixElement prefixElement = maybePrefix; | 771 PrefixElement prefixElement = maybePrefix; |
| 829 if (prefixElement.isDeferred) { | 772 if (prefixElement.isDeferred) { |
| 830 return prefixElement; | 773 return prefixElement; |
| 831 } | 774 } |
| 832 } | 775 } |
| 833 return null; | 776 return null; |
| 834 } | 777 } |
| 835 } | 778 } |
| OLD | NEW |