| Index: sdk/lib/_internal/compiler/implementation/deferred_load.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
|
| index 8585c4825134d354927f55558c5f9eff19717d6f..dfd6e4d8d0dad946d0e430a156c6b0aa95da09a8 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
|
| @@ -119,10 +119,15 @@ class DeferredLoadTask extends CompilerTask {
|
| /// Will be `true` if the program contains deferred libraries.
|
| bool splitProgram = false;
|
|
|
| - /// A mapping from the name of a [DeferredLibrary] annotation to all dependent
|
| - /// output units.
|
| - final Map<String, Set<OutputUnit>> hunksToLoad =
|
| - new Map<String, Set<OutputUnit>>();
|
| + /// A mapping from the name of a defer import to all the output units it
|
| + /// depends on in a list of lists to be loaded in the order they appear.
|
| + ///
|
| + /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3],
|
| + /// [lib1]]} would mean that in order to load "lib1" first the hunk
|
| + /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3
|
| + /// can be loaded in parallel. And finally lib1 can be loaded.
|
| + final Map<String, List<List<OutputUnit>>> hunksToLoad =
|
| + new Map<String, List<List<OutputUnit>>>();
|
| final Map<Import, String> importDeferName = new Map<Import, String>();
|
|
|
| /// A mapping from elements and constants to their output unit. Query this via
|
| @@ -446,8 +451,7 @@ class DeferredLoadTask extends CompilerTask {
|
| void mapDependenciesIfResolved(Element element) {
|
| // If there is a target for this class, but no use of mirrors the
|
| // class will not be resolved. We just skip it.
|
| - if (element is ClassElement &&
|
| - !(element as ClassElement).isResolved) {
|
| + if (element is ClassElement &&!element.isResolved) {
|
| return;
|
| }
|
| _mapDependencies(element, deferredImport);
|
| @@ -628,15 +632,36 @@ class DeferredLoadTask extends CompilerTask {
|
| for (OutputUnit outputUnit in allOutputUnits) {
|
| computeOutputUnitName(outputUnit);
|
| }
|
| + List sortedOutputUnits = new List.from(allOutputUnits);
|
| + // Sort the output units in descending order of the number of imports they
|
| + // include.
|
| +
|
| + // The loading of the output units mut be ordered because a superclass needs
|
| + // to be initialized before its subclass.
|
| + // But a class can only depend on another class in an output unit shared by
|
| + // a strict superset of the imports:
|
| + // By contradiction: Assume a class C in output unit shared by imports in
|
| + // the set S1 = (lib1,.., lib_n) depends on a class D in an output unit
|
| + // shared by S2 such that S2 not a superset of S1. Let lib_s be a library in
|
| + // S1 not in S2. lib_s must depend on C, and then in turn on D therefore D
|
| + // is not in the right output unit.
|
| + sortedOutputUnits.sort((a, b) => b.imports.length - a.imports.length);
|
|
|
| // For each deferred import we find out which outputUnits to load.
|
| for (Import import in _allDeferredImports.keys) {
|
| if (import == _fakeMainImport) continue;
|
| - hunksToLoad[importDeferName[import]] = new Set<OutputUnit>();
|
| - for (OutputUnit outputUnit in allOutputUnits) {
|
| + hunksToLoad[importDeferName[import]] = new List<List<OutputUnit>>();
|
| + int lastNumberOfImports = 0;
|
| + List<OutputUnit> currentLastList;
|
| + for (OutputUnit outputUnit in sortedOutputUnits) {
|
| if (outputUnit == mainOutputUnit) continue;
|
| if (outputUnit.imports.contains(import)) {
|
| - hunksToLoad[importDeferName[import]].add(outputUnit);
|
| + if (outputUnit.imports.length != lastNumberOfImports) {
|
| + lastNumberOfImports = outputUnit.imports.length;
|
| + currentLastList = new List<OutputUnit>();
|
| + hunksToLoad[importDeferName[import]].add(currentLastList);
|
| + }
|
| + currentLastList.add(outputUnit);
|
| }
|
| }
|
| }
|
|
|