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 Compiler, | 8 Compiler, |
9 CompilerTask, | 9 CompilerTask, |
10 Constant, | 10 Constant, |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 /// The OutputUnit that will be loaded when the program starts. | 112 /// The OutputUnit that will be loaded when the program starts. |
113 final OutputUnit mainOutputUnit = new OutputUnit(); | 113 final OutputUnit mainOutputUnit = new OutputUnit(); |
114 | 114 |
115 /// A set containing (eventually) all output units that will result from the | 115 /// A set containing (eventually) all output units that will result from the |
116 /// program. | 116 /// program. |
117 final Set<OutputUnit> allOutputUnits = new Set<OutputUnit>(); | 117 final Set<OutputUnit> allOutputUnits = new Set<OutputUnit>(); |
118 | 118 |
119 /// Will be `true` if the program contains deferred libraries. | 119 /// Will be `true` if the program contains deferred libraries. |
120 bool splitProgram = false; | 120 bool splitProgram = false; |
121 | 121 |
122 /// A mapping from the name of a [DeferredLibrary] annotation to all dependent | 122 /// A mapping from the name of a defer import to all the output units it |
123 /// output units. | 123 /// depends on in a list of lists to be loaded in the order they appear. |
124 final Map<String, Set<OutputUnit>> hunksToLoad = | 124 /// |
125 new Map<String, Set<OutputUnit>>(); | 125 /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3], |
| 126 /// [lib1]]} would mean that in order to load "lib1" first the hunk |
| 127 /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3 |
| 128 /// can be loaded in parallel. And finally lib1 can be loaded. |
| 129 final Map<String, List<List<OutputUnit>>> hunksToLoad = |
| 130 new Map<String, List<List<OutputUnit>>>(); |
126 final Map<Import, String> importDeferName = new Map<Import, String>(); | 131 final Map<Import, String> importDeferName = new Map<Import, String>(); |
127 | 132 |
128 /// A mapping from elements and constants to their output unit. Query this via | 133 /// A mapping from elements and constants to their output unit. Query this via |
129 /// [outputUnitForElement] | 134 /// [outputUnitForElement] |
130 final Map<Element, OutputUnit> _elementToOutputUnit = | 135 final Map<Element, OutputUnit> _elementToOutputUnit = |
131 new Map<Element, OutputUnit>(); | 136 new Map<Element, OutputUnit>(); |
132 | 137 |
133 /// A mapping from constants to their output unit. Query this via | 138 /// A mapping from constants to their output unit. Query this via |
134 /// [outputUnitForConstant] | 139 /// [outputUnitForConstant] |
135 final Map<Constant, OutputUnit> _constantToOutputUnit = | 140 final Map<Constant, OutputUnit> _constantToOutputUnit = |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 mirrorTask.analyzer.collectMirrorsUsedAnnotation(); | 444 mirrorTask.analyzer.collectMirrorsUsedAnnotation(); |
440 | 445 |
441 // If there is a MirrorsUsed annotation we add only the needed | 446 // If there is a MirrorsUsed annotation we add only the needed |
442 // things to the output units for the library. | 447 // things to the output units for the library. |
443 List<MirrorUsage> mirrorUsages = mirrorsResult[library]; | 448 List<MirrorUsage> mirrorUsages = mirrorsResult[library]; |
444 if (mirrorUsages == null) continue; | 449 if (mirrorUsages == null) continue; |
445 | 450 |
446 void mapDependenciesIfResolved(Element element) { | 451 void mapDependenciesIfResolved(Element element) { |
447 // If there is a target for this class, but no use of mirrors the | 452 // If there is a target for this class, but no use of mirrors the |
448 // class will not be resolved. We just skip it. | 453 // class will not be resolved. We just skip it. |
449 if (element is ClassElement && | 454 if (element is ClassElement &&!element.isResolved) { |
450 !(element as ClassElement).isResolved) { | |
451 return; | 455 return; |
452 } | 456 } |
453 _mapDependencies(element, deferredImport); | 457 _mapDependencies(element, deferredImport); |
454 } | 458 } |
455 | 459 |
456 for (MirrorUsage usage in mirrorUsages) { | 460 for (MirrorUsage usage in mirrorUsages) { |
457 if (usage.targets != null) { | 461 if (usage.targets != null) { |
458 for (Element dependency in usage.targets) { | 462 for (Element dependency in usage.targets) { |
459 if (dependency.isLibrary()) { | 463 if (dependency.isLibrary()) { |
460 LibraryElement library = dependency; | 464 LibraryElement library = dependency; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 generatedNames[outputUnit] = outputUnit.name; | 625 generatedNames[outputUnit] = outputUnit.name; |
622 } | 626 } |
623 | 627 |
624 for (Import import in _allDeferredImports.keys) { | 628 for (Import import in _allDeferredImports.keys) { |
625 computeImportDeferName(import); | 629 computeImportDeferName(import); |
626 } | 630 } |
627 | 631 |
628 for (OutputUnit outputUnit in allOutputUnits) { | 632 for (OutputUnit outputUnit in allOutputUnits) { |
629 computeOutputUnitName(outputUnit); | 633 computeOutputUnitName(outputUnit); |
630 } | 634 } |
| 635 List sortedOutputUnits = new List.from(allOutputUnits); |
| 636 // Sort the output units in descending order of the number of imports they |
| 637 // include. |
| 638 |
| 639 // The loading of the output units mut be ordered because a superclass needs |
| 640 // to be initialized before its subclass. |
| 641 // But a class can only depend on another class in an output unit shared by |
| 642 // a strict superset of the imports: |
| 643 // By contradiction: Assume a class C in output unit shared by imports in |
| 644 // the set S1 = (lib1,.., lib_n) depends on a class D in an output unit |
| 645 // shared by S2 such that S2 not a superset of S1. Let lib_s be a library in |
| 646 // S1 not in S2. lib_s must depend on C, and then in turn on D therefore D |
| 647 // is not in the right output unit. |
| 648 sortedOutputUnits.sort((a, b) => b.imports.length - a.imports.length); |
631 | 649 |
632 // For each deferred import we find out which outputUnits to load. | 650 // For each deferred import we find out which outputUnits to load. |
633 for (Import import in _allDeferredImports.keys) { | 651 for (Import import in _allDeferredImports.keys) { |
634 if (import == _fakeMainImport) continue; | 652 if (import == _fakeMainImport) continue; |
635 hunksToLoad[importDeferName[import]] = new Set<OutputUnit>(); | 653 hunksToLoad[importDeferName[import]] = new List<List<OutputUnit>>(); |
636 for (OutputUnit outputUnit in allOutputUnits) { | 654 int lastNumberOfImports = 0; |
| 655 List<OutputUnit> currentLastList; |
| 656 for (OutputUnit outputUnit in sortedOutputUnits) { |
637 if (outputUnit == mainOutputUnit) continue; | 657 if (outputUnit == mainOutputUnit) continue; |
638 if (outputUnit.imports.contains(import)) { | 658 if (outputUnit.imports.contains(import)) { |
639 hunksToLoad[importDeferName[import]].add(outputUnit); | 659 if (outputUnit.imports.length != lastNumberOfImports) { |
| 660 lastNumberOfImports = outputUnit.imports.length; |
| 661 currentLastList = new List<OutputUnit>(); |
| 662 hunksToLoad[importDeferName[import]].add(currentLastList); |
| 663 } |
| 664 currentLastList.add(outputUnit); |
640 } | 665 } |
641 } | 666 } |
642 } | 667 } |
643 } | 668 } |
644 | 669 |
645 void onResolutionComplete(FunctionElement main) { | 670 void onResolutionComplete(FunctionElement main) { |
646 if (!splitProgram) { | 671 if (!splitProgram) { |
647 allOutputUnits.add(mainOutputUnit); | 672 allOutputUnits.add(mainOutputUnit); |
648 return; | 673 return; |
649 } | 674 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 } | 793 } |
769 if (splitProgram && compiler.backend is DartBackend) { | 794 if (splitProgram && compiler.backend is DartBackend) { |
770 // TODO(sigurdm): Implement deferred loading for dart2dart. | 795 // TODO(sigurdm): Implement deferred loading for dart2dart. |
771 splitProgram = false; | 796 splitProgram = false; |
772 compiler.reportInfo( | 797 compiler.reportInfo( |
773 lastDeferred, | 798 lastDeferred, |
774 MessageKind.DEFERRED_LIBRARY_DART_2_DART); | 799 MessageKind.DEFERRED_LIBRARY_DART_2_DART); |
775 } | 800 } |
776 } | 801 } |
777 } | 802 } |
OLD | NEW |