| 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 defer import to all the output units it | 122 /// A mapping from the name of a [DeferredLibrary] annotation to all dependent |
| 123 /// depends on in a list of lists to be loaded in the order they appear. | 123 /// output units. |
| 124 /// | 124 final Map<String, Set<OutputUnit>> hunksToLoad = |
| 125 /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3], | 125 new Map<String, Set<OutputUnit>>(); |
| 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>>>(); | |
| 131 final Map<Import, String> importDeferName = new Map<Import, String>(); | 126 final Map<Import, String> importDeferName = new Map<Import, String>(); |
| 132 | 127 |
| 133 /// A mapping from elements and constants to their output unit. Query this via | 128 /// A mapping from elements and constants to their output unit. Query this via |
| 134 /// [outputUnitForElement] | 129 /// [outputUnitForElement] |
| 135 final Map<Element, OutputUnit> _elementToOutputUnit = | 130 final Map<Element, OutputUnit> _elementToOutputUnit = |
| 136 new Map<Element, OutputUnit>(); | 131 new Map<Element, OutputUnit>(); |
| 137 | 132 |
| 138 /// A mapping from constants to their output unit. Query this via | 133 /// A mapping from constants to their output unit. Query this via |
| 139 /// [outputUnitForConstant] | 134 /// [outputUnitForConstant] |
| 140 final Map<Constant, OutputUnit> _constantToOutputUnit = | 135 final Map<Constant, OutputUnit> _constantToOutputUnit = |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 mirrorTask.analyzer.collectMirrorsUsedAnnotation(); | 439 mirrorTask.analyzer.collectMirrorsUsedAnnotation(); |
| 445 | 440 |
| 446 // If there is a MirrorsUsed annotation we add only the needed | 441 // If there is a MirrorsUsed annotation we add only the needed |
| 447 // things to the output units for the library. | 442 // things to the output units for the library. |
| 448 List<MirrorUsage> mirrorUsages = mirrorsResult[library]; | 443 List<MirrorUsage> mirrorUsages = mirrorsResult[library]; |
| 449 if (mirrorUsages == null) continue; | 444 if (mirrorUsages == null) continue; |
| 450 | 445 |
| 451 void mapDependenciesIfResolved(Element element) { | 446 void mapDependenciesIfResolved(Element element) { |
| 452 // If there is a target for this class, but no use of mirrors the | 447 // If there is a target for this class, but no use of mirrors the |
| 453 // class will not be resolved. We just skip it. | 448 // class will not be resolved. We just skip it. |
| 454 if (element is ClassElement &&!element.isResolved) { | 449 if (element is ClassElement && |
| 450 !(element as ClassElement).isResolved) { |
| 455 return; | 451 return; |
| 456 } | 452 } |
| 457 _mapDependencies(element, deferredImport); | 453 _mapDependencies(element, deferredImport); |
| 458 } | 454 } |
| 459 | 455 |
| 460 for (MirrorUsage usage in mirrorUsages) { | 456 for (MirrorUsage usage in mirrorUsages) { |
| 461 if (usage.targets != null) { | 457 if (usage.targets != null) { |
| 462 for (Element dependency in usage.targets) { | 458 for (Element dependency in usage.targets) { |
| 463 if (dependency.isLibrary()) { | 459 if (dependency.isLibrary()) { |
| 464 LibraryElement library = dependency; | 460 LibraryElement library = dependency; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 generatedNames[outputUnit] = outputUnit.name; | 621 generatedNames[outputUnit] = outputUnit.name; |
| 626 } | 622 } |
| 627 | 623 |
| 628 for (Import import in _allDeferredImports.keys) { | 624 for (Import import in _allDeferredImports.keys) { |
| 629 computeImportDeferName(import); | 625 computeImportDeferName(import); |
| 630 } | 626 } |
| 631 | 627 |
| 632 for (OutputUnit outputUnit in allOutputUnits) { | 628 for (OutputUnit outputUnit in allOutputUnits) { |
| 633 computeOutputUnitName(outputUnit); | 629 computeOutputUnitName(outputUnit); |
| 634 } | 630 } |
| 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); | |
| 649 | 631 |
| 650 // For each deferred import we find out which outputUnits to load. | 632 // For each deferred import we find out which outputUnits to load. |
| 651 for (Import import in _allDeferredImports.keys) { | 633 for (Import import in _allDeferredImports.keys) { |
| 652 if (import == _fakeMainImport) continue; | 634 if (import == _fakeMainImport) continue; |
| 653 hunksToLoad[importDeferName[import]] = new List<List<OutputUnit>>(); | 635 hunksToLoad[importDeferName[import]] = new Set<OutputUnit>(); |
| 654 int lastNumberOfImports = 0; | 636 for (OutputUnit outputUnit in allOutputUnits) { |
| 655 List<OutputUnit> currentLastList; | |
| 656 for (OutputUnit outputUnit in sortedOutputUnits) { | |
| 657 if (outputUnit == mainOutputUnit) continue; | 637 if (outputUnit == mainOutputUnit) continue; |
| 658 if (outputUnit.imports.contains(import)) { | 638 if (outputUnit.imports.contains(import)) { |
| 659 if (outputUnit.imports.length != lastNumberOfImports) { | 639 hunksToLoad[importDeferName[import]].add(outputUnit); |
| 660 lastNumberOfImports = outputUnit.imports.length; | |
| 661 currentLastList = new List<OutputUnit>(); | |
| 662 hunksToLoad[importDeferName[import]].add(currentLastList); | |
| 663 } | |
| 664 currentLastList.add(outputUnit); | |
| 665 } | 640 } |
| 666 } | 641 } |
| 667 } | 642 } |
| 668 } | 643 } |
| 669 | 644 |
| 670 void onResolutionComplete(FunctionElement main) { | 645 void onResolutionComplete(FunctionElement main) { |
| 671 if (!splitProgram) { | 646 if (!splitProgram) { |
| 672 allOutputUnits.add(mainOutputUnit); | 647 allOutputUnits.add(mainOutputUnit); |
| 673 return; | 648 return; |
| 674 } | 649 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 } | 768 } |
| 794 if (splitProgram && compiler.backend is DartBackend) { | 769 if (splitProgram && compiler.backend is DartBackend) { |
| 795 // TODO(sigurdm): Implement deferred loading for dart2dart. | 770 // TODO(sigurdm): Implement deferred loading for dart2dart. |
| 796 splitProgram = false; | 771 splitProgram = false; |
| 797 compiler.reportInfo( | 772 compiler.reportInfo( |
| 798 lastDeferred, | 773 lastDeferred, |
| 799 MessageKind.DEFERRED_LIBRARY_DART_2_DART); | 774 MessageKind.DEFERRED_LIBRARY_DART_2_DART); |
| 800 } | 775 } |
| 801 } | 776 } |
| 802 } | 777 } |
| OLD | NEW |