Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: pkg/compiler/lib/src/deferred_load.dart

Issue 1434103004: dart2js: report output unit imports to dump-info (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « DEPS ('k') | pkg/compiler/lib/src/dump_info.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 'common.dart'; 7 import 'common.dart';
8 import 'common/backend_api.dart' show 8 import 'common/backend_api.dart' show
9 Backend; 9 Backend;
10 import 'common/tasks.dart' show 10 import 'common/tasks.dart' show
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 /// OutputUnits are equal if their [imports] are equal. 71 /// OutputUnits are equal if their [imports] are equal.
72 class OutputUnit { 72 class OutputUnit {
73 /// The deferred imports that will load this output unit when one of them is 73 /// The deferred imports that will load this output unit when one of them is
74 /// loaded. 74 /// loaded.
75 final Setlet<_DeferredImport> imports = new Setlet<_DeferredImport>(); 75 final Setlet<_DeferredImport> imports = new Setlet<_DeferredImport>();
76 76
77 /// `true` if this output unit is for the main output file. 77 /// `true` if this output unit is for the main output file.
78 final bool isMainOutput; 78 final bool isMainOutput;
79 79
80 /// A unique name representing this [OutputUnit]. 80 /// A unique name representing this [OutputUnit].
81 /// Based on the set of [imports].
82 String name; 81 String name;
83 82
84 OutputUnit({this.isMainOutput: false}); 83 OutputUnit({this.isMainOutput: false});
85 84
86 String toString() => "OutputUnit($name)"; 85 String toString() => "OutputUnit($name)";
87 86
88 bool operator==(OutputUnit other) { 87 bool operator==(OutputUnit other) {
89 return imports.length == other.imports.length && 88 return imports.length == other.imports.length &&
90 imports.containsAll(other.imports); 89 imports.containsAll(other.imports);
91 } 90 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 124
126 /// A mapping from the name of a defer import to all the output units it 125 /// A mapping from the name of a defer import to all the output units it
127 /// depends on in a list of lists to be loaded in the order they appear. 126 /// depends on in a list of lists to be loaded in the order they appear.
128 /// 127 ///
129 /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3], 128 /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3],
130 /// [lib1]]} would mean that in order to load "lib1" first the hunk 129 /// [lib1]]} would mean that in order to load "lib1" first the hunk
131 /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3 130 /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3
132 /// can be loaded in parallel. And finally lib1 can be loaded. 131 /// can be loaded in parallel. And finally lib1 can be loaded.
133 final Map<String, List<OutputUnit>> hunksToLoad = 132 final Map<String, List<OutputUnit>> hunksToLoad =
134 new Map<String, List<OutputUnit>>(); 133 new Map<String, List<OutputUnit>>();
135 final Map<_DeferredImport, String> _importDeferName = 134
135 /// A cache of the result of calling `computeImportDeferName` on the keys of
136 /// this map.
137 final Map<_DeferredImport, String> importDeferName =
136 <_DeferredImport, String>{}; 138 <_DeferredImport, String>{};
137 139
138 /// A mapping from elements and constants to their output unit. Query this via 140 /// A mapping from elements and constants to their output unit. Query this via
139 /// [outputUnitForElement] 141 /// [outputUnitForElement]
140 final Map<Element, OutputUnit> _elementToOutputUnit = 142 final Map<Element, OutputUnit> _elementToOutputUnit =
141 new Map<Element, OutputUnit>(); 143 new Map<Element, OutputUnit>();
142 144
143 /// A mapping from constants to their output unit. Query this via 145 /// A mapping from constants to their output unit. Query this via
144 /// [outputUnitForConstant] 146 /// [outputUnitForConstant]
145 final Map<ConstantValue, OutputUnit> _constantToOutputUnit = 147 final Map<ConstantValue, OutputUnit> _constantToOutputUnit =
146 new Map<ConstantValue, OutputUnit>(); 148 new Map<ConstantValue, OutputUnit>();
147 149
148 /// All the imports with a [DeferredLibrary] annotation, mapped to the 150 /// All the imports with a [DeferredLibrary] annotation, mapped to the
149 /// [LibraryElement] they import. 151 /// [LibraryElement] they import.
150 /// The main library is included in this set for convenience. 152 /// The main library is included in this set for convenience.
151 final Map<_DeferredImport, LibraryElement> _allDeferredImports = 153 final Map<_DeferredImport, LibraryElement> _allDeferredImports =
152 new Map<_DeferredImport, LibraryElement>(); 154 new Map<_DeferredImport, LibraryElement>();
153 155
154 /// Because the token-stream is forgotten later in the program, we cache a 156 /// Because the token-stream is forgotten later in the program, we cache a
155 /// description of each deferred import. 157 /// description of each deferred import.
156 final Map<_DeferredImport, ImportDescription>_deferredImportDescriptions = 158 final Map<_DeferredImport, ImportDescription> _deferredImportDescriptions =
157 <_DeferredImport, ImportDescription>{}; 159 <_DeferredImport, ImportDescription>{};
158 160
159 // For each deferred import we want to know exactly what elements have to 161 // For each deferred import we want to know exactly what elements have to
160 // be loaded. 162 // be loaded.
161 Map<_DeferredImport, Set<Element>> _importedDeferredBy = null; 163 Map<_DeferredImport, Set<Element>> _importedDeferredBy = null;
162 Map<_DeferredImport, Set<ConstantValue>> _constantsDeferredBy = null; 164 Map<_DeferredImport, Set<ConstantValue>> _constantsDeferredBy = null;
163 165
164 Set<Element> _mainElements = new Set<Element>(); 166 Set<Element> _mainElements = new Set<Element>();
165 167
166 DeferredLoadTask(Compiler compiler) : super(compiler) { 168 DeferredLoadTask(Compiler compiler) : super(compiler) {
(...skipping 28 matching lines...) Expand all
195 return _constantToOutputUnit[constant]; 197 return _constantToOutputUnit[constant];
196 } 198 }
197 199
198 bool isDeferred(Element element) { 200 bool isDeferred(Element element) {
199 return outputUnitForElement(element) != mainOutputUnit; 201 return outputUnitForElement(element) != mainOutputUnit;
200 } 202 }
201 203
202 /// Returns the unique name for the deferred import of [prefix]. 204 /// Returns the unique name for the deferred import of [prefix].
203 String getImportDeferName(Spannable node, PrefixElement prefix) { 205 String getImportDeferName(Spannable node, PrefixElement prefix) {
204 String name = 206 String name =
205 _importDeferName[new _DeclaredDeferredImport(prefix.deferredImport)]; 207 importDeferName[new _DeclaredDeferredImport(prefix.deferredImport)];
206 if (name == null) { 208 if (name == null) {
207 reporter.internalError(node, "No deferred name for $prefix."); 209 reporter.internalError(node, "No deferred name for $prefix.");
208 } 210 }
209 return name; 211 return name;
210 } 212 }
211 213
212 /// Returns `true` if element [to] is reachable from element [from] without 214 /// Returns `true` if element [to] is reachable from element [from] without
213 /// crossing a deferred import. 215 /// crossing a deferred import.
214 /// 216 ///
215 /// For example, if we have two deferred libraries `A` and `B` that both 217 /// For example, if we have two deferred libraries `A` and `B` that both
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 566
565 /// Computes a unique string for the name field for each outputUnit. 567 /// Computes a unique string for the name field for each outputUnit.
566 /// 568 ///
567 /// Also sets up the [hunksToLoad] mapping. 569 /// Also sets up the [hunksToLoad] mapping.
568 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) { 570 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) {
569 Set<String> usedImportNames = new Set<String>(); 571 Set<String> usedImportNames = new Set<String>();
570 572
571 void computeImportDeferName(_DeferredImport import) { 573 void computeImportDeferName(_DeferredImport import) {
572 String result = import.computeImportDeferName(compiler); 574 String result = import.computeImportDeferName(compiler);
573 assert(result != null); 575 assert(result != null);
574 _importDeferName[import] = makeUnique(result, usedImportNames); 576 importDeferName[import] = makeUnique(result, usedImportNames);
575 } 577 }
576 578
577 int counter = 1; 579 int counter = 1;
578 580
579 for (_DeferredImport import in _allDeferredImports.keys) { 581 for (_DeferredImport import in _allDeferredImports.keys) {
580 computeImportDeferName(import); 582 computeImportDeferName(import);
581 } 583 }
582 584
583 for (OutputUnit outputUnit in allOutputUnits) { 585 for (OutputUnit outputUnit in allOutputUnits) {
584 if (outputUnit == mainOutputUnit) { 586 if (outputUnit == mainOutputUnit) {
585 outputUnit.name = "main"; 587 outputUnit.name = "main";
586 } else { 588 } else {
587 outputUnit.name = "$counter"; 589 outputUnit.name = "$counter";
588 ++counter; 590 ++counter;
589 } 591 }
590 } 592 }
591 593
592 List sortedOutputUnits = new List.from(allOutputUnits); 594 List sortedOutputUnits = new List.from(allOutputUnits);
593 // Sort the output units in descending order of the number of imports they 595 // Sort the output units in descending order of the number of imports they
594 // include. 596 // include.
595 597
596 // The loading of the output units mut be ordered because a superclass needs 598 // The loading of the output units must be ordered because a superclass
597 // to be initialized before its subclass. 599 // needs to be initialized before its subclass.
598 // But a class can only depend on another class in an output unit shared by 600 // But a class can only depend on another class in an output unit shared by
599 // a strict superset of the imports: 601 // a strict superset of the imports:
600 // By contradiction: Assume a class C in output unit shared by imports in 602 // By contradiction: Assume a class C in output unit shared by imports in
601 // the set S1 = (lib1,.., lib_n) depends on a class D in an output unit 603 // the set S1 = (lib1,.., lib_n) depends on a class D in an output unit
602 // shared by S2 such that S2 not a superset of S1. Let lib_s be a library in 604 // shared by S2 such that S2 not a superset of S1. Let lib_s be a library in
603 // S1 not in S2. lib_s must depend on C, and then in turn on D therefore D 605 // S1 not in S2. lib_s must depend on C, and then in turn on D. Therefore D
604 // is not in the right output unit. 606 // is not in the right output unit.
605 sortedOutputUnits.sort((a, b) => b.imports.length - a.imports.length); 607 sortedOutputUnits.sort((a, b) => b.imports.length - a.imports.length);
606 608
607 // For each deferred import we find out which outputUnits to load. 609 // For each deferred import we find out which outputUnits to load.
608 for (_DeferredImport import in _allDeferredImports.keys) { 610 for (_DeferredImport import in _allDeferredImports.keys) {
609 if (import == _fakeMainImport) continue; 611 if (import == _fakeMainImport) continue;
610 hunksToLoad[_importDeferName[import]] = new List<OutputUnit>(); 612 hunksToLoad[importDeferName[import]] = new List<OutputUnit>();
611 for (OutputUnit outputUnit in sortedOutputUnits) { 613 for (OutputUnit outputUnit in sortedOutputUnits) {
612 if (outputUnit == mainOutputUnit) continue; 614 if (outputUnit == mainOutputUnit) continue;
613 if (outputUnit.imports.contains(import)) { 615 if (outputUnit.imports.contains(import)) {
614 hunksToLoad[_importDeferName[import]].add(outputUnit); 616 hunksToLoad[importDeferName[import]].add(outputUnit);
615 } 617 }
616 } 618 }
617 } 619 }
618 } 620 }
619 621
620 void onResolutionComplete(FunctionElement main) { 622 void onResolutionComplete(FunctionElement main) {
621 if (!isProgramSplit) { 623 if (!isProgramSplit) {
622 allOutputUnits.add(mainOutputUnit); 624 allOutputUnits.add(mainOutputUnit);
623 return; 625 return;
624 } 626 }
625 if (main == null) return; 627 if (main == null) return;
626 LibraryElement mainLibrary = main.library; 628 LibraryElement mainLibrary = main.library;
627 _importedDeferredBy = new Map<_DeferredImport, Set<Element>>(); 629 _importedDeferredBy = new Map<_DeferredImport, Set<Element>>();
628 _constantsDeferredBy = new Map<_DeferredImport, Set<ConstantValue>>(); 630 _constantsDeferredBy = new Map<_DeferredImport, Set<ConstantValue>>();
629 _importedDeferredBy[_fakeMainImport] = _mainElements; 631 _importedDeferredBy[_fakeMainImport] = _mainElements;
630 632
631 measureElement(mainLibrary, () { 633 measureElement(mainLibrary, () {
632 634
633 // Starting from main, traverse the program and find all dependencies. 635 // Starting from main, traverse the program and find all dependencies.
634 _mapDependencies(element: compiler.mainFunction, import: _fakeMainImport); 636 _mapDependencies(element: compiler.mainFunction, import: _fakeMainImport);
635 637
636 // Also add "global" dependencies to the main OutputUnit. These are 638 // Also add "global" dependencies to the main OutputUnit. These are
637 // things that the backend need but cannot associate with a particular 639 // things that the backend needs but cannot associate with a particular
638 // element, for example, startRootIsolate. This set also contains 640 // element, for example, startRootIsolate. This set also contains
639 // elements for which we lack precise information. 641 // elements for which we lack precise information.
640 for (Element element in compiler.globalDependencies.otherDependencies) { 642 for (Element element in compiler.globalDependencies.otherDependencies) {
641 _mapDependencies(element: element, import: _fakeMainImport); 643 _mapDependencies(element: element, import: _fakeMainImport);
642 } 644 }
643 645
644 // Now check to see if we have to add more elements due to mirrors. 646 // Now check to see if we have to add more elements due to mirrors.
645 if (compiler.mirrorsLibrary != null) { 647 if (compiler.mirrorsLibrary != null) {
646 _addMirrorElements(); 648 _addMirrorElements();
647 } 649 }
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 return null; 859 return null;
858 } 860 }
859 861
860 /// Returns a json-style map for describing what files that are loaded by a 862 /// Returns a json-style map for describing what files that are loaded by a
861 /// given deferred import. 863 /// given deferred import.
862 /// The mapping is structured as: 864 /// The mapping is structured as:
863 /// library uri -> {"name": library name, "files": (prefix -> list of files)} 865 /// library uri -> {"name": library name, "files": (prefix -> list of files)}
864 /// Where 866 /// Where
865 /// 867 ///
866 /// - <library uri> is the relative uri of the library making a deferred 868 /// - <library uri> is the relative uri of the library making a deferred
867 /// import 869 /// import.
868 /// - <library name> is the name of the libary, and "<unnamed>" if it is 870 /// - <library name> is the name of the library, and "<unnamed>" if it is
869 /// unnamed. 871 /// unnamed.
870 /// - <prefix> is the `as` prefix used for a given deferred import. 872 /// - <prefix> is the `as` prefix used for a given deferred import.
871 /// - <list of files> is a list of the filenames the must be loaded when that 873 /// - <list of files> is a list of the filenames the must be loaded when that
872 /// import is loaded. 874 /// import is loaded.
873 Map<String, Map<String, dynamic>> computeDeferredMap() { 875 Map<String, Map<String, dynamic>> computeDeferredMap() {
874 JavaScriptBackend backend = compiler.backend; 876 JavaScriptBackend backend = compiler.backend;
875 Map<String, Map<String, dynamic>> mapping = 877 Map<String, Map<String, dynamic>> mapping =
876 new Map<String, Map<String, dynamic>>(); 878 new Map<String, Map<String, dynamic>>();
877 _deferredImportDescriptions.keys.forEach((_DeferredImport import) { 879 _deferredImportDescriptions.keys.forEach((_DeferredImport import) {
878 List<OutputUnit> outputUnits = hunksToLoad[_importDeferName[import]]; 880 List<OutputUnit> outputUnits = hunksToLoad[importDeferName[import]];
879 ImportDescription description = _deferredImportDescriptions[import]; 881 ImportDescription description = _deferredImportDescriptions[import];
880 Map<String, dynamic> libraryMap = 882 Map<String, dynamic> libraryMap =
881 mapping.putIfAbsent(description.importingUri, 883 mapping.putIfAbsent(description.importingUri,
882 () => <String, dynamic>{"name": description.importingLibraryName, 884 () => <String, dynamic>{"name": description.importingLibraryName,
883 "imports": <String, List<String>>{}}); 885 "imports": <String, List<String>>{}});
884 886
885 libraryMap["imports"][description.prefix] = outputUnits.map( 887 libraryMap["imports"][importDeferName[import]] = outputUnits.map(
886 (OutputUnit outputUnit) { 888 (OutputUnit outputUnit) {
887 return backend.deferredPartFileName(outputUnit.name); 889 return backend.deferredPartFileName(outputUnit.name);
888 }).toList(); 890 }).toList();
889 }); 891 });
890 return mapping; 892 return mapping;
891 } 893 }
892 894
893 /// Creates a textual representation of the output unit content. 895 /// Creates a textual representation of the output unit content.
894 String dump() { 896 String dump() {
895 Map<OutputUnit, List<String>> elementMap = <OutputUnit, List<String>>{}; 897 Map<OutputUnit, List<String>> elementMap = <OutputUnit, List<String>>{};
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 return result; 998 return result;
997 } 999 }
998 1000
999 bool operator ==(other) { 1001 bool operator ==(other) {
1000 if (other is! _DeclaredDeferredImport) return false; 1002 if (other is! _DeclaredDeferredImport) return false;
1001 return declaration == other.declaration; 1003 return declaration == other.declaration;
1002 } 1004 }
1003 1005
1004 int get hashCode => declaration.hashCode * 17; 1006 int get hashCode => declaration.hashCode * 17;
1005 } 1007 }
OLDNEW
« no previous file with comments | « DEPS ('k') | pkg/compiler/lib/src/dump_info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698