| 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 b0192972f828aee0544a2007de1b73b2099d6034..b4ef154f4a0e134a4ebbe6326991f26ff048c9fe 100644
|
| --- a/pkg/compiler/lib/src/deferred_load.dart
|
| +++ b/pkg/compiler/lib/src/deferred_load.dart
|
| @@ -194,7 +194,6 @@ class DeferredLoadTask extends CompilerTask {
|
| /// Returns the [OutputUnit] where [constant] belongs.
|
| OutputUnit outputUnitForConstant(ConstantValue constant) {
|
| if (!isProgramSplit) return mainOutputUnit;
|
| -
|
| return _constantToOutputUnit[constant];
|
| }
|
|
|
| @@ -249,16 +248,6 @@ class DeferredLoadTask extends CompilerTask {
|
| Set<ConstantValue> constants,
|
| isMirrorUsage) {
|
|
|
| - /// Recursively add the constant and its dependencies to [constants].
|
| - void addConstants(ConstantValue constant) {
|
| - if (constants.contains(constant)) return;
|
| - constants.add(constant);
|
| - if (constant is ConstructedConstantValue) {
|
| - elements.add(constant.type.element);
|
| - }
|
| - constant.getDependencies().forEach(addConstants);
|
| - }
|
| -
|
| /// Collects all direct dependencies of [element].
|
| ///
|
| /// The collected dependent elements and constants are are added to
|
| @@ -289,7 +278,7 @@ class DeferredLoadTask extends CompilerTask {
|
| }
|
| treeElements.forEachConstantNode((Node node, _) {
|
| // Explicitly depend on the backend constants.
|
| - addConstants(
|
| + constants.add(
|
| backend.constants.getConstantForNode(node, treeElements).value);
|
| });
|
| elements.addAll(treeElements.otherDependencies);
|
| @@ -300,7 +289,7 @@ class DeferredLoadTask extends CompilerTask {
|
| ConstantExpression constant =
|
| backend.constants.getConstantForMetadata(metadata);
|
| if (constant != null) {
|
| - addConstants(constant.value);
|
| + constants.add(constant.value);
|
| }
|
| }
|
|
|
| @@ -401,40 +390,70 @@ class DeferredLoadTask extends CompilerTask {
|
| return result;
|
| }
|
|
|
| - /// Recursively traverses the graph of dependencies from [element], mapping
|
| - /// deferred imports to each dependency it needs in the sets
|
| - /// [_importedDeferredBy] and [_constantsDeferredBy].
|
| - void _mapDependencies(Element element, Import import,
|
| - {isMirrorUsage: false}) {
|
| - Set<Element> elements = _importedDeferredBy.putIfAbsent(import,
|
| - () => new Set<Element>());
|
| + /// Add all dependencies of [constant] to the mapping of [import].
|
| + void _mapConstantDependencies(ConstantValue constant, Import import) {
|
| Set<ConstantValue> constants = _constantsDeferredBy.putIfAbsent(import,
|
| () => new Set<ConstantValue>());
|
| + if (constants.contains(constant)) return;
|
| + constants.add(constant);
|
| + if (constant is ConstructedConstantValue) {
|
| + _mapDependencies(element: constant.type.element, import: import);
|
| + }
|
| + constant.getDependencies().forEach((ConstantValue dependency) {
|
| + _mapConstantDependencies(dependency, import);
|
| + });
|
| + }
|
|
|
| - // Only process elements once, unless we are doing dependencies due to
|
| - // mirrors, which are added in additional traversals.
|
| - if (!isMirrorUsage && elements.contains(element)) return;
|
| - // Anything used directly by main will be loaded from the start
|
| - // We do not need to traverse it again.
|
| - if (import != _fakeMainImport && _mainElements.contains(element)) return;
|
| + /// Recursively traverses the graph of dependencies from one of [element]
|
| + /// or [constant], mapping deferred imports to each dependency it needs in the
|
| + /// sets [_importedDeferredBy] and [_constantsDeferredBy].
|
| + /// Only one of [element] and [constant] should be given.
|
| + void _mapDependencies({Element element,
|
| + Import import,
|
| + isMirrorUsage: false}) {
|
| +
|
| + Set<Element> elements = _importedDeferredBy.putIfAbsent(import,
|
| + () => new Set<Element>());
|
|
|
| - // Here we modify [_importedDeferredBy].
|
| - elements.add(element);
|
|
|
| Set<Element> dependentElements = new Set<Element>();
|
| + Set<ConstantValue> dependentConstants = new Set<ConstantValue>();
|
|
|
| - // This call can modify [_importedDeferredBy] and [_constantsDeferredBy].
|
| - _collectAllElementsAndConstantsResolvedFrom(
|
| - element, dependentElements, constants, isMirrorUsage);
|
| + LibraryElement library;
|
| +
|
| + if (element != null) {
|
| + // Only process elements once, unless we are doing dependencies due to
|
| + // mirrors, which are added in additional traversals.
|
| + if (!isMirrorUsage && elements.contains(element)) return;
|
| + // Anything used directly by main will be loaded from the start
|
| + // We do not need to traverse it again.
|
| + if (import != _fakeMainImport && _mainElements.contains(element)) return;
|
| + elements.add(element);
|
| +
|
| +
|
| + // This call can modify [dependentElements] and [dependentConstants].
|
| + _collectAllElementsAndConstantsResolvedFrom(
|
| + element, dependentElements, dependentConstants, isMirrorUsage);
|
| +
|
| + library = element.library;
|
| + }
|
|
|
| - LibraryElement library = element.library;
|
| for (Element dependency in dependentElements) {
|
| if (_isExplicitlyDeferred(dependency, library)) {
|
| for (Import deferredImport in _getImports(dependency, library)) {
|
| - _mapDependencies(dependency, deferredImport);
|
| - };
|
| + _mapDependencies(element: dependency, import: deferredImport);
|
| + }
|
| + } else {
|
| + _mapDependencies(element: dependency, import: import);
|
| + }
|
| + }
|
| +
|
| + for (ConstantValue dependency in dependentConstants) {
|
| + if (dependency is DeferredConstantValue) {
|
| + _mapConstantDependencies(dependency,
|
| + dependency.prefix.deferredImport);
|
| } else {
|
| - _mapDependencies(dependency, import);
|
| + _mapConstantDependencies(dependency, import);
|
| }
|
| }
|
| }
|
| @@ -451,7 +470,8 @@ class DeferredLoadTask extends CompilerTask {
|
| // So we have to filter them out here.
|
| if (element is AnalyzableElementX && !element.hasTreeElements) return;
|
| if (compiler.backend.isAccessibleByReflection(element)) {
|
| - _mapDependencies(element, deferredImport, isMirrorUsage: true);
|
| + _mapDependencies(element: element, import: deferredImport,
|
| + isMirrorUsage: true);
|
| }
|
| }
|
|
|
| @@ -466,8 +486,8 @@ class DeferredLoadTask extends CompilerTask {
|
| ConstantExpression constant =
|
| backend.constants.getConstantForMetadata(metadata);
|
| if (constant != null) {
|
| - _mapDependencies(constant.value.getType(compiler.coreTypes).element,
|
| - deferredImport);
|
| + _mapConstantDependencies(constant.value,
|
| + deferredImport);
|
| }
|
| }
|
| for (LibraryTag tag in library.tags) {
|
| @@ -475,8 +495,8 @@ class DeferredLoadTask extends CompilerTask {
|
| ConstantExpression constant =
|
| backend.constants.getConstantForMetadata(metadata);
|
| if (constant != null) {
|
| - _mapDependencies(constant.value.getType(compiler.coreTypes).element,
|
| - deferredImport);
|
| + _mapConstantDependencies(constant.value,
|
| + deferredImport);
|
| }
|
| }
|
| }
|
| @@ -580,14 +600,14 @@ class DeferredLoadTask extends CompilerTask {
|
| measureElement(mainLibrary, () {
|
|
|
| // Starting from main, traverse the program and find all dependencies.
|
| - _mapDependencies(compiler.mainFunction, _fakeMainImport);
|
| + _mapDependencies(element: compiler.mainFunction, import: _fakeMainImport);
|
|
|
| // Also add "global" dependencies to the main OutputUnit. These are
|
| // things that the backend need but cannot associate with a particular
|
| // element, for example, startRootIsolate. This set also contains
|
| // elements for which we lack precise information.
|
| for (Element element in compiler.globalDependencies.otherDependencies) {
|
| - _mapDependencies(element, _fakeMainImport);
|
| + _mapDependencies(element: element, import: _fakeMainImport);
|
| }
|
|
|
| // Now check to see if we have to add more elements due to mirrors.
|
| @@ -615,6 +635,8 @@ class DeferredLoadTask extends CompilerTask {
|
| .imports.add(import);
|
| }
|
| }
|
| + }
|
| + for (Import 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].
|
|
|