Chromium Code Reviews| 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..540d793132bf6cec2bc45c2526d5516a9ca6457e 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); |
|
Johnni Winther
2015/04/30 09:15:03
Weird indentation.
sigurdm
2015/04/30 11:21:44
Done.
|
| } |
| } |
| } |
| @@ -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]. |