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 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 // Assuming class C in output unit shared by imports in the set S1 = | |
|
floitsch
2014/04/03 09:05:20
Add: "By contradition:"
sigurdm
2014/04/03 09:44:51
Done.
| |
| 644 // (lib1,.., lib_n) depends on a class D in an output unit shared by S2 such | |
| 645 // that S2 not a superset of S1. Let lib_s be a library in S1 not in | |
| 646 // S2. lib_s must depend on C, and then in turn on D therefore D is not in | |
| 647 // 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 |