| 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');
|
|
|