| Index: pkg/compiler/lib/src/deferred_load.dart
|
| diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
|
| index b92a38db06c3c90f2a737d1400882d93e65d04ec..5f929e3b397d52778d1ef95bb10e87e4b6a68051 100644
|
| --- a/pkg/compiler/lib/src/deferred_load.dart
|
| +++ b/pkg/compiler/lib/src/deferred_load.dart
|
| @@ -18,6 +18,8 @@ import 'constants/values.dart' show
|
| import 'dart_types.dart';
|
| import 'diagnostics/messages.dart' show
|
| MessageKind;
|
| +import 'diagnostics/spannable.dart' show
|
| + Spannable;
|
| import 'elements/elements.dart' show
|
| AccessorElement,
|
| AstElement,
|
| @@ -66,7 +68,7 @@ import 'util/util.dart' show
|
| class OutputUnit {
|
| /// The deferred imports that will load this output unit when one of them is
|
| /// loaded.
|
| - final Setlet<Import> imports = new Setlet<Import>();
|
| + final Setlet<_DeferredImport> imports = new Setlet<_DeferredImport>();
|
|
|
| /// `true` if this output unit is for the main output file.
|
| final bool isMainOutput;
|
| @@ -86,7 +88,7 @@ class OutputUnit {
|
|
|
| int get hashCode {
|
| int sum = 0;
|
| - for (Import import in imports) {
|
| + for (_DeferredImport import in imports) {
|
| sum = (sum + import.hashCode) & 0x3FFFFFFF; // Stay in 30 bit range.
|
| }
|
| return sum;
|
| @@ -105,8 +107,7 @@ class DeferredLoadTask extends CompilerTask {
|
|
|
| /// A synthetic [Import] representing the loading of the main
|
| /// program.
|
| - final Import _fakeMainImport = new Import(null, new LiteralString(null,
|
| - new LiteralDartString("main")), null, null, null);
|
| + final _DeferredImport _fakeMainImport = const _DeferredImport();
|
|
|
| /// The OutputUnit that will be loaded when the program starts.
|
| final OutputUnit mainOutputUnit = new OutputUnit(isMainOutput: true);
|
| @@ -127,7 +128,8 @@ class DeferredLoadTask extends CompilerTask {
|
| /// can be loaded in parallel. And finally lib1 can be loaded.
|
| final Map<String, List<OutputUnit>> hunksToLoad =
|
| new Map<String, List<OutputUnit>>();
|
| - final Map<Import, String> importDeferName = new Map<Import, String>();
|
| + final Map<_DeferredImport, String> _importDeferName =
|
| + <_DeferredImport, String>{};
|
|
|
| /// A mapping from elements and constants to their output unit. Query this via
|
| /// [outputUnitForElement]
|
| @@ -142,17 +144,18 @@ class DeferredLoadTask extends CompilerTask {
|
| /// All the imports with a [DeferredLibrary] annotation, mapped to the
|
| /// [LibraryElement] they import.
|
| /// The main library is included in this set for convenience.
|
| - final Map<Import, LibraryElement> _allDeferredImports =
|
| - new Map<Import, LibraryElement>();
|
| + final Map<_DeferredImport, LibraryElement> _allDeferredImports =
|
| + new Map<_DeferredImport, LibraryElement>();
|
|
|
| /// Because the token-stream is forgotten later in the program, we cache a
|
| /// description of each deferred import.
|
| - final _deferredImportDescriptions = new Map<Import, ImportDescription>();
|
| + final Map<_DeferredImport, ImportDescription>_deferredImportDescriptions =
|
| + <_DeferredImport, ImportDescription>{};
|
|
|
| // For each deferred import we want to know exactly what elements have to
|
| // be loaded.
|
| - Map<Import, Set<Element>> _importedDeferredBy = null;
|
| - Map<Import, Set<ConstantValue>> _constantsDeferredBy = null;
|
| + Map<_DeferredImport, Set<Element>> _importedDeferredBy = null;
|
| + Map<_DeferredImport, Set<ConstantValue>> _constantsDeferredBy = null;
|
|
|
| Set<Element> _mainElements = new Set<Element>();
|
|
|
| @@ -192,6 +195,16 @@ class DeferredLoadTask extends CompilerTask {
|
| return outputUnitForElement(element) != mainOutputUnit;
|
| }
|
|
|
| + /// Returns the unique name for the deferred import of [prefix].
|
| + String getImportDeferName(Spannable node, PrefixElement prefix) {
|
| + String name =
|
| + _importDeferName[new _DeclaredDeferredImport(prefix.deferredImport)];
|
| + if (name == null) {
|
| + compiler.internalError(node, "No deferred name for $prefix.");
|
| + }
|
| + return name;
|
| + }
|
| +
|
| /// Returns `true` if element [to] is reachable from element [from] without
|
| /// crossing a deferred import.
|
| ///
|
| @@ -207,7 +220,7 @@ class DeferredLoadTask extends CompilerTask {
|
| void registerConstantDeferredUse(DeferredConstantValue constant,
|
| PrefixElement prefix) {
|
| OutputUnit outputUnit = new OutputUnit();
|
| - outputUnit.imports.add(prefix.deferredImport);
|
| + outputUnit.imports.add(new _DeclaredDeferredImport(prefix.deferredImport));
|
| _constantToOutputUnit[constant] = outputUnit;
|
| }
|
|
|
| @@ -405,7 +418,8 @@ class DeferredLoadTask extends CompilerTask {
|
| }
|
|
|
| /// Add all dependencies of [constant] to the mapping of [import].
|
| - void _mapConstantDependencies(ConstantValue constant, Import import) {
|
| + void _mapConstantDependencies(ConstantValue constant,
|
| + _DeferredImport import) {
|
| Set<ConstantValue> constants = _constantsDeferredBy.putIfAbsent(import,
|
| () => new Set<ConstantValue>());
|
| if (constants.contains(constant)) return;
|
| @@ -423,7 +437,7 @@ class DeferredLoadTask extends CompilerTask {
|
| /// sets [_importedDeferredBy] and [_constantsDeferredBy].
|
| /// Only one of [element] and [constant] should be given.
|
| void _mapDependencies({Element element,
|
| - Import import,
|
| + _DeferredImport import,
|
| isMirrorUsage: false}) {
|
|
|
| Set<Element> elements = _importedDeferredBy.putIfAbsent(import,
|
| @@ -455,7 +469,9 @@ class DeferredLoadTask extends CompilerTask {
|
| for (Element dependency in dependentElements) {
|
| if (_isExplicitlyDeferred(dependency, library)) {
|
| for (Import deferredImport in _getImports(dependency, library)) {
|
| - _mapDependencies(element: dependency, import: deferredImport);
|
| + _mapDependencies(
|
| + element: dependency,
|
| + import: new _DeclaredDeferredImport(deferredImport));
|
| }
|
| } else {
|
| _mapDependencies(element: dependency, import: import);
|
| @@ -465,7 +481,7 @@ class DeferredLoadTask extends CompilerTask {
|
| for (ConstantValue dependency in dependentConstants) {
|
| if (dependency is DeferredConstantValue) {
|
| _mapConstantDependencies(dependency,
|
| - dependency.prefix.deferredImport);
|
| + new _DeclaredDeferredImport(dependency.prefix.deferredImport));
|
| } else {
|
| _mapConstantDependencies(dependency, import);
|
| }
|
| @@ -476,7 +492,8 @@ class DeferredLoadTask extends CompilerTask {
|
| ///
|
| /// The elements are added with [_mapDependencies].
|
| void _addMirrorElements() {
|
| - void mapDependenciesIfResolved(Element element, Import deferredImport) {
|
| + void mapDependenciesIfResolved(Element element,
|
| + _DeferredImport deferredImport) {
|
| // If an element is the target of a MirrorsUsed annotation but never used
|
| // It will not be resolved, and we should not call isNeededForReflection.
|
| // TODO(sigurdm): Unresolved elements should just answer false when
|
| @@ -491,7 +508,7 @@ class DeferredLoadTask extends CompilerTask {
|
|
|
| // For each deferred import we analyze all elements reachable from the
|
| // imported library through non-deferred imports.
|
| - handleLibrary(LibraryElement library, Import deferredImport) {
|
| + handleLibrary(LibraryElement library, _DeferredImport deferredImport) {
|
| library.implementation.forEachLocalMember((Element element) {
|
| mapDependenciesIfResolved(element, deferredImport);
|
| });
|
| @@ -514,7 +531,7 @@ class DeferredLoadTask extends CompilerTask {
|
| }
|
| }
|
|
|
| - for (Import deferredImport in _allDeferredImports.keys) {
|
| + for (_DeferredImport deferredImport in _allDeferredImports.keys) {
|
| LibraryElement deferredLibrary = _allDeferredImports[deferredImport];
|
| for (LibraryElement library in
|
| _nonDeferredReachableLibraries(deferredLibrary)) {
|
| @@ -529,36 +546,15 @@ class DeferredLoadTask extends CompilerTask {
|
| void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) {
|
| Set<String> usedImportNames = new Set<String>();
|
|
|
| - // Finds the first argument to the [DeferredLibrary] annotation
|
| - void computeImportDeferName(Import import) {
|
| - String result;
|
| - if (import == _fakeMainImport) {
|
| - result = "main";
|
| - } else if (import.isDeferred) {
|
| - result = import.prefix.toString();
|
| - } else {
|
| - List<MetadataAnnotation> metadatas = import.metadata;
|
| - assert(metadatas != null);
|
| - for (MetadataAnnotation metadata in metadatas) {
|
| - metadata.ensureResolved(compiler);
|
| - ConstantValue value =
|
| - compiler.constants.getConstantValue(metadata.constant);
|
| - Element element = value.getType(compiler.coreTypes).element;
|
| - if (element == deferredLibraryClass) {
|
| - ConstructedConstantValue constant = value;
|
| - StringConstantValue s = constant.fields.values.single;
|
| - result = s.primitiveValue.slowToString();
|
| - break;
|
| - }
|
| - }
|
| - }
|
| + void computeImportDeferName(_DeferredImport import) {
|
| + String result = import.computeImportDeferName(compiler);
|
| assert(result != null);
|
| - importDeferName[import] = makeUnique(result, usedImportNames);;
|
| + _importDeferName[import] = makeUnique(result, usedImportNames);
|
| }
|
|
|
| int counter = 1;
|
|
|
| - for (Import import in _allDeferredImports.keys) {
|
| + for (_DeferredImport import in _allDeferredImports.keys) {
|
| computeImportDeferName(import);
|
| }
|
|
|
| @@ -587,13 +583,13 @@ class DeferredLoadTask extends CompilerTask {
|
| 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) {
|
| + for (_DeferredImport import in _allDeferredImports.keys) {
|
| if (import == _fakeMainImport) continue;
|
| - hunksToLoad[importDeferName[import]] = new List<OutputUnit>();
|
| + hunksToLoad[_importDeferName[import]] = new List<OutputUnit>();
|
| for (OutputUnit outputUnit in sortedOutputUnits) {
|
| if (outputUnit == mainOutputUnit) continue;
|
| if (outputUnit.imports.contains(import)) {
|
| - hunksToLoad[importDeferName[import]].add(outputUnit);
|
| + hunksToLoad[_importDeferName[import]].add(outputUnit);
|
| }
|
| }
|
| }
|
| @@ -606,8 +602,8 @@ class DeferredLoadTask extends CompilerTask {
|
| }
|
| if (main == null) return;
|
| LibraryElement mainLibrary = main.library;
|
| - _importedDeferredBy = new Map<Import, Set<Element>>();
|
| - _constantsDeferredBy = new Map<Import, Set<ConstantValue>>();
|
| + _importedDeferredBy = new Map<_DeferredImport, Set<Element>>();
|
| + _constantsDeferredBy = new Map<_DeferredImport, Set<ConstantValue>>();
|
| _importedDeferredBy[_fakeMainImport] = _mainElements;
|
|
|
| measureElement(mainLibrary, () {
|
| @@ -636,7 +632,7 @@ class DeferredLoadTask extends CompilerTask {
|
|
|
| // Reverse the mappings. For each element record an OutputUnit collecting
|
| // all deferred imports mapped to this element. Same for constants.
|
| - for (Import import in _importedDeferredBy.keys) {
|
| + for (_DeferredImport import in _importedDeferredBy.keys) {
|
| for (Element element in _importedDeferredBy[import]) {
|
| // Only one file should be loaded when the program starts, so make
|
| // sure that only one OutputUnit is created for [fakeMainImport].
|
| @@ -649,7 +645,7 @@ class DeferredLoadTask extends CompilerTask {
|
| }
|
| }
|
| }
|
| - for (Import import in _constantsDeferredBy.keys) {
|
| + for (_DeferredImport import in _constantsDeferredBy.keys) {
|
| for (ConstantValue constant in _constantsDeferredBy[import]) {
|
| // Only one file should be loaded when the program starts, so make
|
| // sure that only one OutputUnit is created for [fakeMainImport].
|
| @@ -748,15 +744,16 @@ class DeferredLoadTask extends CompilerTask {
|
| // The last import we saw with the same prefix.
|
| Import previousDeferredImport = prefixDeferredImport[prefix];
|
| if (import.isDeferred) {
|
| + _DeferredImport key = new _DeclaredDeferredImport(import);
|
| LibraryElement importedLibrary = library.getLibraryFromTag(import);
|
| - _allDeferredImports[import] = importedLibrary;
|
| + _allDeferredImports[key] = importedLibrary;
|
|
|
| if (prefix == null) {
|
| compiler.reportError(import,
|
| MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX);
|
| } else {
|
| prefixDeferredImport[prefix] = import;
|
| - _deferredImportDescriptions[import] =
|
| + _deferredImportDescriptions[key] =
|
| new ImportDescription(import, library, compiler);
|
| }
|
| isProgramSplit = true;
|
| @@ -855,8 +852,8 @@ class DeferredLoadTask extends CompilerTask {
|
| JavaScriptBackend backend = compiler.backend;
|
| Map<String, Map<String, dynamic>> mapping =
|
| new Map<String, Map<String, dynamic>>();
|
| - _deferredImportDescriptions.keys.forEach((ast.Import import) {
|
| - List<OutputUnit> outputUnits = hunksToLoad[importDeferName[import]];
|
| + _deferredImportDescriptions.keys.forEach((_DeferredImport import) {
|
| + List<OutputUnit> outputUnits = hunksToLoad[_importDeferName[import]];
|
| ImportDescription description = _deferredImportDescriptions[import];
|
| Map<String, dynamic> libraryMap =
|
| mapping.putIfAbsent(description.importingUri,
|
| @@ -894,5 +891,54 @@ class ImportDescription {
|
| ? "<unnamed>"
|
| : libraryName;
|
| }
|
| +}
|
| +
|
| +/// A node in the deferred import graph.
|
| +///
|
| +/// This class serves as the root node; the 'import' of the main library.
|
| +class _DeferredImport {
|
| + const _DeferredImport();
|
| +
|
| + /// Computes a suggestive name for this import.
|
| + String computeImportDeferName(Compiler compiler) => 'main';
|
| +}
|
| +
|
| +/// A node in the deferred import graph defined by a deferred import directive.
|
| +class _DeclaredDeferredImport implements _DeferredImport {
|
| + final Import declaration;
|
| +
|
| + _DeclaredDeferredImport(this.declaration);
|
| +
|
| + @override
|
| + String computeImportDeferName(Compiler compiler) {
|
| + String result;
|
| + if (declaration.isDeferred) {
|
| + result = declaration.prefix.toString();
|
| + } else {
|
| + // Finds the first argument to the [DeferredLibrary] annotation
|
| + List<MetadataAnnotation> metadatas = declaration.metadata;
|
| + assert(metadatas != null);
|
| + for (MetadataAnnotation metadata in metadatas) {
|
| + metadata.ensureResolved(compiler);
|
| + ConstantValue value =
|
| + compiler.constants.getConstantValue(metadata.constant);
|
| + Element element = value.getType(compiler.coreTypes).element;
|
| + if (element == compiler.deferredLibraryClass) {
|
| + ConstructedConstantValue constant = value;
|
| + StringConstantValue s = constant.fields.values.single;
|
| + result = s.primitiveValue.slowToString();
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + assert(result != null);
|
| + return result;
|
| + }
|
| +
|
| + bool operator ==(other) {
|
| + if (other is! _DeclaredDeferredImport) return false;
|
| + return declaration == other.declaration;
|
| + }
|
|
|
| + int get hashCode => declaration.hashCode * 17;
|
| }
|
|
|