Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart

Issue 476583003: Allow dart2dart to output one file per library. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address floitsch's comments Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart_backend; 5 part of dart_backend;
6 6
7 // TODO(ahe): This class is simply wrong. This backend should use 7 // TODO(ahe): This class is simply wrong. This backend should use
8 // elements when it can, not AST nodes. Perhaps a [Map<Element, 8 // elements when it can, not AST nodes. Perhaps a [Map<Element,
9 // TreeElements>] is what is needed. 9 // TreeElements>] is what is needed.
10 class ElementAst { 10 class ElementAst {
11 final Node ast; 11 final Node ast;
12 final TreeElements treeElements; 12 final TreeElements treeElements;
13 13
14 ElementAst(AstElement element) 14 ElementAst(AstElement element)
15 : this.internal(element.resolvedAst.node, element.resolvedAst.elements); 15 : this.internal(element.resolvedAst.node, element.resolvedAst.elements);
16 16
17 ElementAst.internal(this.ast, this.treeElements); 17 ElementAst.internal(this.ast, this.treeElements);
18 } 18 }
19 19
20 class DartBackend extends Backend { 20 class DartBackend extends Backend {
21 final List<CompilerTask> tasks; 21 final List<CompilerTask> tasks;
22 final bool forceStripTypes; 22 final bool forceStripTypes;
23 final bool stripAsserts; 23 final bool stripAsserts;
24 // TODO(antonm): make available from command-line options. 24 // TODO(antonm): make available from command-line options.
25 final bool outputAst = false; 25 final bool outputAst = false;
26 final Map<ClassNode, List<Node>> memberNodes; 26 final Map<ClassNode, List<Node>> memberNodes;
27 27
28 /// If `true`, libraries are generated into separate files.
29 final bool multiFile;
30
28 PlaceholderRenamer placeholderRenamer; 31 PlaceholderRenamer placeholderRenamer;
29 32
30 // TODO(zarah) Maybe change this to a command-line option. 33 // TODO(zarah) Maybe change this to a command-line option.
31 // Right now, it is set by the tests. 34 // Right now, it is set by the tests.
32 bool useMirrorHelperLibrary = false; 35 bool useMirrorHelperLibrary = false;
33 36
34 /// Initialized if the useMirrorHelperLibrary field is set. 37 /// Initialized if the useMirrorHelperLibrary field is set.
35 MirrorRenamer mirrorRenamer; 38 MirrorRenamer mirrorRenamer;
36 39
37 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary 40 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 ClassElement element = type.element; 98 ClassElement element = type.element;
96 // Check all supertypes. 99 // Check all supertypes.
97 if (element.allSupertypes != null) { 100 if (element.allSupertypes != null) {
98 element.allSupertypes.forEach(workQueue.add); 101 element.allSupertypes.forEach(workQueue.add);
99 } 102 }
100 } 103 }
101 } 104 }
102 return true; 105 return true;
103 } 106 }
104 107
105 DartBackend(Compiler compiler, List<String> strips) 108 DartBackend(Compiler compiler, List<String> strips, {this.multiFile})
106 : tasks = <CompilerTask>[], 109 : tasks = <CompilerTask>[],
107 memberNodes = new Map<ClassNode, List<Node>>(), 110 memberNodes = new Map<ClassNode, List<Node>>(),
108 forceStripTypes = strips.indexOf('types') != -1, 111 forceStripTypes = strips.indexOf('types') != -1,
109 stripAsserts = strips.indexOf('asserts') != -1, 112 stripAsserts = strips.indexOf('asserts') != -1,
110 constantCompilerTask = new DartConstantTask(compiler), 113 constantCompilerTask = new DartConstantTask(compiler),
111 super(compiler) { 114 super(compiler) {
112 resolutionCallbacks = new DartResolutionCallbacks(this); 115 resolutionCallbacks = new DartResolutionCallbacks(this);
113 } 116 }
114 117
115 bool classNeedsRti(ClassElement cls) => false; 118 bool classNeedsRti(ClassElement cls) => false;
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 } 225 }
223 226
224 final elementAsts = new Map<Element, ElementAst>(); 227 final elementAsts = new Map<Element, ElementAst>();
225 228
226 ElementAst parse(AstElement element) { 229 ElementAst parse(AstElement element) {
227 if (!compiler.irBuilder.hasIr(element)) { 230 if (!compiler.irBuilder.hasIr(element)) {
228 return new ElementAst(element); 231 return new ElementAst(element);
229 } else { 232 } else {
230 cps_ir.FunctionDefinition function = compiler.irBuilder.getIr(element); 233 cps_ir.FunctionDefinition function = compiler.irBuilder.getIr(element);
231 // Transformations on the CPS IR. 234 // Transformations on the CPS IR.
232 compiler.tracer.traceCompilation(element.name, null, compiler); 235 compiler.tracer.traceCompilation(element.name, null, compiler);
233 new ConstantPropagator(compiler, constantSystem).rewrite(function); 236 new ConstantPropagator(compiler, constantSystem).rewrite(function);
234 compiler.tracer.traceGraph("Sparse constant propagation", function); 237 compiler.tracer.traceGraph("Sparse constant propagation", function);
235 new RedundantPhiEliminator().rewrite(function); 238 new RedundantPhiEliminator().rewrite(function);
236 compiler.tracer.traceGraph("Redundant phi elimination", function); 239 compiler.tracer.traceGraph("Redundant phi elimination", function);
237 new ShrinkingReducer().rewrite(function); 240 new ShrinkingReducer().rewrite(function);
238 compiler.tracer.traceGraph("Shrinking reductions", function); 241 compiler.tracer.traceGraph("Shrinking reductions", function);
239 // Do not rewrite the IR after variable allocation. Allocation 242 // Do not rewrite the IR after variable allocation. Allocation
240 // makes decisions based on an approximation of IR variable live 243 // makes decisions based on an approximation of IR variable live
241 // ranges that can be invalidated by transforming the IR. 244 // ranges that can be invalidated by transforming the IR.
242 new cps_ir.RegisterAllocator().visit(function); 245 new cps_ir.RegisterAllocator().visit(function);
(...skipping 16 matching lines...) Expand all
259 compiler.tracer.traceGraph('Unshadow parameters', definition); 262 compiler.tracer.traceGraph('Unshadow parameters', definition);
260 263
261 TreeElementMapping treeElements = new TreeElementMapping(element); 264 TreeElementMapping treeElements = new TreeElementMapping(element);
262 backend_ast.Node backendAst = 265 backend_ast.Node backendAst =
263 backend_ast_emitter.emit(definition); 266 backend_ast_emitter.emit(definition);
264 Node frontend_ast = backend2frontend.emit(treeElements, backendAst); 267 Node frontend_ast = backend2frontend.emit(treeElements, backendAst);
265 return new ElementAst.internal(frontend_ast, treeElements); 268 return new ElementAst.internal(frontend_ast, treeElements);
266 } 269 }
267 } 270 }
268 271
272 List<LibraryElement> userLibraries =
273 compiler.libraryLoader.libraries.where(isUserLibrary).toList();
274
269 Set<Element> topLevelElements = new Set<Element>(); 275 Set<Element> topLevelElements = new Set<Element>();
270 Map<ClassElement, Set<Element>> classMembers = 276 Map<ClassElement, Set<Element>> classMembers =
271 new Map<ClassElement, Set<Element>>(); 277 new Map<ClassElement, Set<Element>>();
272 278
273 // Build all top level elements to emit and necessary class members. 279 // Build all top level elements to emit and necessary class members.
274 var newTypedefElementCallback, newClassElementCallback; 280 var newTypedefElementCallback, newClassElementCallback;
275 281
276 void processElement(Element element, ElementAst elementAst) { 282 void processElement(Element element, ElementAst elementAst) {
277 ReferencedElementCollector collector = 283 ReferencedElementCollector collector =
278 new ReferencedElementCollector(compiler, 284 new ReferencedElementCollector(compiler,
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 } 453 }
448 memberNodes[elementAsts[element].ast] = members; 454 memberNodes[elementAsts[element].ast] = members;
449 } 455 }
450 } 456 }
451 457
452 if (useMirrorHelperLibrary) { 458 if (useMirrorHelperLibrary) {
453 mirrorRenamer.addRenames(placeholderRenamer.renames, 459 mirrorRenamer.addRenames(placeholderRenamer.renames,
454 topLevelNodes, collector); 460 topLevelNodes, collector);
455 } 461 }
456 462
457 final EmitterUnparser unparser = 463 Map<LibraryElement, String> outputPaths = new Map<LibraryElement, String>();
458 new EmitterUnparser(placeholderRenamer.renames, 464 Map<LibraryElement, EmitterUnparser> unparsers =
459 stripTypes: forceStripTypes, 465 new Map<LibraryElement, EmitterUnparser>();
460 minify: compiler.enableMinification); 466
461 for (LibraryElement library in placeholderRenamer.platformImports) { 467 // The single unparser used if we collect all the output in one file.
462 if (library.isPlatformLibrary && !library.isInternalLibrary) { 468 EmitterUnparser mainUnparser = multiFile
463 unparser.unparseImportTag(library.canonicalUri.toString()); 469 ? null
470 : new EmitterUnparser(placeholderRenamer.renames,
471 stripTypes: forceStripTypes,
472 minify: compiler.enableMinification);
473
474 if (multiFile) {
475 // TODO(sigurdm): Factor handling of library-paths out from emitting.
476 String mainName = compiler.outputUri.pathSegments.last;
477 String mainBaseName = mainName.endsWith(".dart")
478 ? mainName.substring(0, mainName.length - 5)
479 : mainName;
480 // Map each library to a path based on the uri of the original
481 // library and [compiler.outputUri].
482 Set<String> usedLibraryPaths = new Set<String>();
483 for (LibraryElement library in userLibraries) {
484 if (library == compiler.mainApp) {
485 outputPaths[library] = mainBaseName;
486 } else {
487 List<String> names =
488 library.canonicalUri.pathSegments.last.split(".");
489 if (names.last == "dart") {
490 names = names.sublist(0, names.length - 1);
491 }
492 outputPaths[library] =
493 "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}";
494 }
495 }
496
497 /// Rewrites imports/exports to refer to the paths given in [outputPaths].
498 for(LibraryElement outputLibrary in userLibraries) {
499 EmitterUnparser unparser = new EmitterUnparser(
500 placeholderRenamer.renames,
501 stripTypes: forceStripTypes,
502 minify: compiler.enableMinification);
503 unparsers[outputLibrary] = unparser;
504 LibraryName libraryName = outputLibrary.libraryTag;
505 if (libraryName != null) {
506 unparser.visitLibraryName(libraryName);
507 }
508 for (LibraryTag tag in outputLibrary.tags) {
509 if (tag is! LibraryDependency) continue;
510 LibraryDependency dependency = tag;
511 LibraryElement libraryElement =
512 outputLibrary.getLibraryFromTag(dependency);
513 String uri = outputPaths.containsKey(libraryElement)
514 ? "${outputPaths[libraryElement]}.dart"
515 : libraryElement.canonicalUri.toString();
516 if (dependency is Import) {
517 unparser.unparseImportTag(uri);
518 } else {
519 unparser.unparseExportTag(uri);
520 }
521 }
522 }
523 } else {
524 for(LibraryElement library in placeholderRenamer.platformImports) {
525 if (library.isPlatformLibrary && !library.isInternalLibrary) {
526 mainUnparser.unparseImportTag(library.canonicalUri.toString());
527 }
464 } 528 }
465 } 529 }
530
466 for (int i = 0; i < sortedTopLevels.length; i++) { 531 for (int i = 0; i < sortedTopLevels.length; i++) {
467 Element element = sortedTopLevels[i]; 532 Element element = sortedTopLevels[i];
468 Node node = topLevelNodes[i]; 533 Node node = topLevelNodes[i];
534 Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser;
469 if (node is ClassNode) { 535 if (node is ClassNode) {
470 // TODO(smok): Filter out default constructors here. 536 // TODO(smok): Filter out default constructors here.
471 unparser.unparseClassWithBody(node, memberNodes[node]); 537 unparser.unparseClassWithBody(node, memberNodes[node]);
472 } else { 538 } else {
473 unparser.unparse(node); 539 unparser.unparse(node);
474 } 540 }
475 unparser.newline(); 541 unparser.newline();
476 } 542 }
477 543
478 compiler.assembledCode = unparser.result; 544 int totalSize = 0;
479 compiler.outputProvider("", "dart") 545 if (multiFile) {
480 ..add(compiler.assembledCode) 546 for(LibraryElement outputLibrary in userLibraries) {
481 ..close(); 547 // TODO(sigurdm): Make the unparser output directly into the buffer inst ead
548 // of caching in `.result`.
549 String code = unparsers[outputLibrary].result;
550 totalSize += code.length;
551 compiler.outputProvider(outputPaths[outputLibrary], "dart")
552 ..add(code)
553 ..close();
554 }
555 // TODO(sigurdm): We should get rid of compiler.assembledCode.
556 compiler.assembledCode = unparsers[compiler.mainApp].result;
557 } else {
558 compiler.assembledCode = mainUnparser.result;
559 compiler.outputProvider("", "dart")
560 ..add(compiler.assembledCode)
561 ..close();
562
563 totalSize = compiler.assembledCode.length;
564 }
565
482 // Output verbose info about size ratio of resulting bundle to all 566 // Output verbose info about size ratio of resulting bundle to all
483 // referenced non-platform sources. 567 // referenced non-platform sources.
484 logResultBundleSizeInfo(topLevelElements); 568 logResultBundleSizeInfo(topLevelElements, totalSize);
485 } 569 }
486 570
487 void logResultBundleSizeInfo(Set<Element> topLevelElements) { 571 void logResultBundleSizeInfo(Set<Element> topLevelElements,
572 int totalOutputSize) {
488 Iterable<LibraryElement> referencedLibraries = 573 Iterable<LibraryElement> referencedLibraries =
489 compiler.libraryLoader.libraries.where(isUserLibrary); 574 compiler.libraryLoader.libraries.where(isUserLibrary);
490 // Sum total size of scripts in each referenced library. 575 // Sum total size of scripts in each referenced library.
491 int nonPlatformSize = 0; 576 int nonPlatformSize = 0;
492 for (LibraryElement lib in referencedLibraries) { 577 for (LibraryElement lib in referencedLibraries) {
493 for (CompilationUnitElement compilationUnit in lib.compilationUnits) { 578 for (CompilationUnitElement compilationUnit in lib.compilationUnits) {
494 nonPlatformSize += compilationUnit.script.file.length; 579 nonPlatformSize += compilationUnit.script.file.length;
495 } 580 }
496 } 581 }
497 int percentage = compiler.assembledCode.length * 100 ~/ nonPlatformSize; 582 int percentage = totalOutputSize * 100 ~/ nonPlatformSize;
498 log('Total used non-platform files size: ${nonPlatformSize} bytes, ' 583 log('Total used non-platform files size: ${nonPlatformSize} bytes, '
499 'bundle size: ${compiler.assembledCode.length} bytes (${percentage}%)'); 584 'Output total size: $totalOutputSize bytes (${percentage}%)');
500 } 585 }
501 586
502 log(String message) => compiler.log('[DartBackend] $message'); 587 log(String message) => compiler.log('[DartBackend] $message');
503 588
504 Future onLibrariesLoaded(Map<Uri, LibraryElement> loadedLibraries) { 589 Future onLibrariesLoaded(Map<Uri, LibraryElement> loadedLibraries) {
505 // All platform classes must be resolved to ensure that their member names 590 // All platform classes must be resolved to ensure that their member names
506 // are preserved. 591 // are preserved.
507 loadedLibraries.values.forEach((LibraryElement library) { 592 loadedLibraries.values.forEach((LibraryElement library) {
508 if (library.isPlatformLibrary) { 593 if (library.isPlatformLibrary) {
509 library.forEachLocalMember((Element element) { 594 library.forEachLocalMember((Element element) {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 } 781 }
697 782
698 Constant compileMetadata(MetadataAnnotation metadata, 783 Constant compileMetadata(MetadataAnnotation metadata,
699 Node node, 784 Node node,
700 TreeElements elements) { 785 TreeElements elements) {
701 return measure(() { 786 return measure(() {
702 return constantCompiler.compileMetadata(metadata, node, elements); 787 return constantCompiler.compileMetadata(metadata, node, elements);
703 }); 788 });
704 } 789 }
705 } 790 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698