Index: sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart |
index ae2cca4dbfae059046b302165209fe8ff03a0406..4160a2777d3533c1cba4bcc018c90c1d4ed126bd 100644 |
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart |
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart |
@@ -25,6 +25,9 @@ class DartBackend extends Backend { |
final bool outputAst = false; |
final Map<ClassNode, List<Node>> memberNodes; |
+ /// If `true`, libraries are generated into separate files. |
+ final bool multiFile; |
+ |
PlaceholderRenamer placeholderRenamer; |
// TODO(zarah) Maybe change this to a command-line option. |
@@ -102,7 +105,7 @@ class DartBackend extends Backend { |
return true; |
} |
- DartBackend(Compiler compiler, List<String> strips) |
+ DartBackend(Compiler compiler, List<String> strips, {this.multiFile}) |
: tasks = <CompilerTask>[], |
memberNodes = new Map<ClassNode, List<Node>>(), |
forceStripTypes = strips.indexOf('types') != -1, |
@@ -229,7 +232,7 @@ class DartBackend extends Backend { |
} else { |
cps_ir.FunctionDefinition function = compiler.irBuilder.getIr(element); |
// Transformations on the CPS IR. |
- compiler.tracer.traceCompilation(element.name, null, compiler); |
+ compiler.tracer.traceCompilation(element.name, null, compiler); |
new ConstantPropagator(compiler, constantSystem).rewrite(function); |
compiler.tracer.traceGraph("Sparse constant propagation", function); |
new RedundantPhiEliminator().rewrite(function); |
@@ -266,6 +269,9 @@ class DartBackend extends Backend { |
} |
} |
+ List<LibraryElement> userLibraries = |
+ compiler.libraryLoader.libraries.where(isUserLibrary).toList(); |
+ |
Set<Element> topLevelElements = new Set<Element>(); |
Map<ClassElement, Set<Element>> classMembers = |
new Map<ClassElement, Set<Element>>(); |
@@ -454,18 +460,78 @@ class DartBackend extends Backend { |
topLevelNodes, collector); |
} |
- final EmitterUnparser unparser = |
- new EmitterUnparser(placeholderRenamer.renames, |
- stripTypes: forceStripTypes, |
- minify: compiler.enableMinification); |
- for (LibraryElement library in placeholderRenamer.platformImports) { |
- if (library.isPlatformLibrary && !library.isInternalLibrary) { |
- unparser.unparseImportTag(library.canonicalUri.toString()); |
+ Map<LibraryElement, String> outputPaths = new Map<LibraryElement, String>(); |
+ Map<LibraryElement, EmitterUnparser> unparsers = |
+ new Map<LibraryElement, EmitterUnparser>(); |
+ |
+ // The single unparser used if we collect all the output in one file. |
+ EmitterUnparser mainUnparser = multiFile |
+ ? null |
+ : new EmitterUnparser(placeholderRenamer.renames, |
+ stripTypes: forceStripTypes, |
+ minify: compiler.enableMinification); |
+ |
+ if (multiFile) { |
+ // TODO(sigurdm): Factor handling of library-paths out from emitting. |
+ String mainName = compiler.outputUri.pathSegments.last; |
+ String mainBaseName = mainName.endsWith(".dart") |
+ ? mainName.substring(0, mainName.length - 5) |
+ : mainName; |
+ // Map each library to a path based on the uri of the original |
+ // library and [compiler.outputUri]. |
+ Set<String> usedLibraryPaths = new Set<String>(); |
+ for (LibraryElement library in userLibraries) { |
+ if (library == compiler.mainApp) { |
+ outputPaths[library] = mainBaseName; |
+ } else { |
+ List<String> names = |
+ library.canonicalUri.pathSegments.last.split("."); |
+ if (names.last == "dart") { |
+ names = names.sublist(0, names.length - 1); |
+ } |
+ outputPaths[library] = |
+ "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}"; |
+ } |
+ } |
+ |
+ /// Rewrites imports/exports to refer to the paths given in [outputPaths]. |
+ for(LibraryElement outputLibrary in userLibraries) { |
+ EmitterUnparser unparser = new EmitterUnparser( |
+ placeholderRenamer.renames, |
+ stripTypes: forceStripTypes, |
+ minify: compiler.enableMinification); |
+ unparsers[outputLibrary] = unparser; |
+ LibraryName libraryName = outputLibrary.libraryTag; |
+ if (libraryName != null) { |
+ unparser.visitLibraryName(libraryName); |
+ } |
+ for (LibraryTag tag in outputLibrary.tags) { |
+ if (tag is! LibraryDependency) continue; |
+ LibraryDependency dependency = tag; |
+ LibraryElement libraryElement = |
+ outputLibrary.getLibraryFromTag(dependency); |
+ String uri = outputPaths.containsKey(libraryElement) |
+ ? "${outputPaths[libraryElement]}.dart" |
+ : libraryElement.canonicalUri.toString(); |
+ if (dependency is Import) { |
+ unparser.unparseImportTag(uri); |
+ } else { |
+ unparser.unparseExportTag(uri); |
+ } |
+ } |
+ } |
+ } else { |
+ for(LibraryElement library in placeholderRenamer.platformImports) { |
+ if (library.isPlatformLibrary && !library.isInternalLibrary) { |
+ mainUnparser.unparseImportTag(library.canonicalUri.toString()); |
+ } |
} |
} |
+ |
for (int i = 0; i < sortedTopLevels.length; i++) { |
Element element = sortedTopLevels[i]; |
Node node = topLevelNodes[i]; |
+ Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser; |
if (node is ClassNode) { |
// TODO(smok): Filter out default constructors here. |
unparser.unparseClassWithBody(node, memberNodes[node]); |
@@ -475,16 +541,35 @@ class DartBackend extends Backend { |
unparser.newline(); |
} |
- compiler.assembledCode = unparser.result; |
- compiler.outputProvider("", "dart") |
- ..add(compiler.assembledCode) |
- ..close(); |
+ int totalSize = 0; |
+ if (multiFile) { |
+ for(LibraryElement outputLibrary in userLibraries) { |
+ // TODO(sigurdm): Make the unparser output directly into the buffer instead |
+ // of caching in `.result`. |
+ String code = unparsers[outputLibrary].result; |
+ totalSize += code.length; |
+ compiler.outputProvider(outputPaths[outputLibrary], "dart") |
+ ..add(code) |
+ ..close(); |
+ } |
+ // TODO(sigurdm): We should get rid of compiler.assembledCode. |
+ compiler.assembledCode = unparsers[compiler.mainApp].result; |
+ } else { |
+ compiler.assembledCode = mainUnparser.result; |
+ compiler.outputProvider("", "dart") |
+ ..add(compiler.assembledCode) |
+ ..close(); |
+ |
+ totalSize = compiler.assembledCode.length; |
+ } |
+ |
// Output verbose info about size ratio of resulting bundle to all |
// referenced non-platform sources. |
- logResultBundleSizeInfo(topLevelElements); |
+ logResultBundleSizeInfo(topLevelElements, totalSize); |
} |
- void logResultBundleSizeInfo(Set<Element> topLevelElements) { |
+ void logResultBundleSizeInfo(Set<Element> topLevelElements, |
+ int totalOutputSize) { |
Iterable<LibraryElement> referencedLibraries = |
compiler.libraryLoader.libraries.where(isUserLibrary); |
// Sum total size of scripts in each referenced library. |
@@ -494,9 +579,9 @@ class DartBackend extends Backend { |
nonPlatformSize += compilationUnit.script.file.length; |
} |
} |
- int percentage = compiler.assembledCode.length * 100 ~/ nonPlatformSize; |
+ int percentage = totalOutputSize * 100 ~/ nonPlatformSize; |
log('Total used non-platform files size: ${nonPlatformSize} bytes, ' |
- 'bundle size: ${compiler.assembledCode.length} bytes (${percentage}%)'); |
+ 'Output total size: $totalOutputSize bytes (${percentage}%)'); |
} |
log(String message) => compiler.log('[DartBackend] $message'); |