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

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

Issue 448943004: Refactor and simplify the dart2dart renamer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix minifying name generation Created 6 years, 4 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<Node, String> renames;
27 final Map<LibraryElement, String> imports;
28 final Map<ClassNode, List<Node>> memberNodes; 26 final Map<ClassNode, List<Node>> memberNodes;
29 Map<Element, LibraryElement> reexportingLibraries; 27
28 PlaceholderRenamer placeholderRenamer;
30 29
31 // TODO(zarah) Maybe change this to a command-line option. 30 // TODO(zarah) Maybe change this to a command-line option.
32 // Right now, it is set by the tests. 31 // Right now, it is set by the tests.
33 bool useMirrorHelperLibrary = false; 32 bool useMirrorHelperLibrary = false;
34 33
35 /// Initialized if the useMirrorHelperLibrary field is set. 34 /// Initialized if the useMirrorHelperLibrary field is set.
36 MirrorRenamer mirrorRenamer; 35 MirrorRenamer mirrorRenamer;
37 36
38 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary 37 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary
39 /// field is set. 38 /// field is set.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 if (element.allSupertypes != null) { 97 if (element.allSupertypes != null) {
99 element.allSupertypes.forEach(workQueue.add); 98 element.allSupertypes.forEach(workQueue.add);
100 } 99 }
101 } 100 }
102 } 101 }
103 return true; 102 return true;
104 } 103 }
105 104
106 DartBackend(Compiler compiler, List<String> strips) 105 DartBackend(Compiler compiler, List<String> strips)
107 : tasks = <CompilerTask>[], 106 : tasks = <CompilerTask>[],
108 renames = new Map<Node, String>(),
109 imports = new Map<LibraryElement, String>(),
110 memberNodes = new Map<ClassNode, List<Node>>(), 107 memberNodes = new Map<ClassNode, List<Node>>(),
111 reexportingLibraries = <Element, LibraryElement>{},
112 forceStripTypes = strips.indexOf('types') != -1, 108 forceStripTypes = strips.indexOf('types') != -1,
113 stripAsserts = strips.indexOf('asserts') != -1, 109 stripAsserts = strips.indexOf('asserts') != -1,
114 constantCompilerTask = new DartConstantTask(compiler), 110 constantCompilerTask = new DartConstantTask(compiler),
115 super(compiler) { 111 super(compiler) {
116 resolutionCallbacks = new DartResolutionCallbacks(this); 112 resolutionCallbacks = new DartResolutionCallbacks(this);
117 } 113 }
118 114
119 bool classNeedsRti(ClassElement cls) => false; 115 bool classNeedsRti(ClassElement cls) => false;
120 bool methodNeedsRti(FunctionElement function) => false; 116 bool methodNeedsRti(FunctionElement function) => false;
121 117
(...skipping 30 matching lines...) Expand all
152 element is !AbstractFieldElement) 148 element is !AbstractFieldElement)
153 || element.library == mirrorHelperLibrary; 149 || element.library == mirrorHelperLibrary;
154 } 150 }
155 151
156 void assembleProgram() { 152 void assembleProgram() {
157 // Conservatively traverse all platform libraries and collect member names. 153 // Conservatively traverse all platform libraries and collect member names.
158 // TODO(antonm): ideally we should only collect names of used members, 154 // TODO(antonm): ideally we should only collect names of used members,
159 // however as of today there are problems with names of some core library 155 // however as of today there are problems with names of some core library
160 // interfaces, most probably for interfaces of literals. 156 // interfaces, most probably for interfaces of literals.
161 final fixedMemberNames = new Set<String>(); 157 final fixedMemberNames = new Set<String>();
158
159 Map<Element, LibraryElement> reexportingLibraries =
160 <Element, LibraryElement>{};
161
162 for (final library in compiler.libraryLoader.libraries) { 162 for (final library in compiler.libraryLoader.libraries) {
163 if (!library.isPlatformLibrary) continue; 163 if (!library.isPlatformLibrary) continue;
164 library.forEachLocalMember((Element element) { 164 library.forEachLocalMember((Element element) {
165 if (element.isClass) { 165 if (element.isClass) {
166 ClassElement classElement = element; 166 ClassElement classElement = element;
167 assert(invariant(classElement, classElement.isResolved, 167 assert(invariant(classElement, classElement.isResolved,
168 message: "Unresolved platform class.")); 168 message: "Unresolved platform class."));
169 classElement.forEachLocalMember((member) { 169 classElement.forEachLocalMember((member) {
170 final name = member.name; 170 final name = member.name;
171 // Skip operator names. 171 // Skip operator names.
172 if (!name.startsWith(r'operator$')) { 172 if (!name.startsWith(r'operator$')) {
173 // Fetch name of named constructors and factories if any, 173 // Fetch name of named constructors and factories if any,
174 // otherwise store regular name. 174 // otherwise store regular name.
175 // TODO(antonm): better way to analyze the name. 175 // TODO(antonm): better way to analyze the name.
176 fixedMemberNames.add(name.split(r'$').last); 176 fixedMemberNames.add(name.split(r'$').last);
177 } 177 }
178 }); 178 });
179 } 179 }
180 // Even class names are added due to a delicate problem we have: 180 // Even class names are added due to a delicate problem we have:
181 // if one imports dart:core with a prefix, we cannot tell prefix.name 181 // if one imports dart:core with a prefix, we cannot tell prefix.name
182 // from dynamic invocation (alas!). So we'd better err on preserving 182 // from dynamic invocation (alas!). So we'd better err on preserving
183 // those names. 183 // those names.
184 fixedMemberNames.add(element.name); 184 fixedMemberNames.add(element.name);
185 }); 185 });
186
186 for (Element export in library.exports) { 187 for (Element export in library.exports) {
187 if (!library.isInternalLibrary && 188 if (!library.isInternalLibrary &&
188 export.library.isInternalLibrary) { 189 export.library.isInternalLibrary) {
189 // If an element of an internal library is reexported by a platform 190 // If an element of an internal library is reexported by a platform
190 // library, we have to import the reexporting library instead of the 191 // library, we have to import the reexporting library instead of the
191 // internal library, because the internal library is an 192 // internal library, because the internal library is an
192 // implementation detail of dart2js. 193 // implementation detail of dart2js.
193 reexportingLibraries[export] = library; 194 reexportingLibraries[export] = library;
194 } 195 }
195 } 196 }
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 392
392 if (element.isClass) { 393 if (element.isClass) {
393 classMembers[element].forEach(makePlaceholders); 394 classMembers[element].forEach(makePlaceholders);
394 } 395 }
395 } 396 }
396 topLevelElements.forEach(makePlaceholders); 397 topLevelElements.forEach(makePlaceholders);
397 // Create renames. 398 // Create renames.
398 bool shouldCutDeclarationTypes = forceStripTypes 399 bool shouldCutDeclarationTypes = forceStripTypes
399 || (compiler.enableMinification 400 || (compiler.enableMinification
400 && isSafeToRemoveTypeDeclarations(classMembers)); 401 && isSafeToRemoveTypeDeclarations(classMembers));
401 renamePlaceholders( 402
402 compiler, collector, renames, imports, 403 placeholderRenamer =
403 fixedMemberNames, reexportingLibraries, 404 new PlaceholderRenamer(compiler, fixedMemberNames, reexportingLibraries,
404 shouldCutDeclarationTypes, 405 cutDeclarationTypes: shouldCutDeclarationTypes);
405 uniqueGlobalNaming: useMirrorHelperLibrary); 406
407 placeholderRenamer.computeRenames(collector);
406 408
407 // Sort elements. 409 // Sort elements.
408 final sortedTopLevels = sortElements(topLevelElements); 410 final List<Element> sortedTopLevels = sortElements(topLevelElements);
409 final sortedClassMembers = new Map<ClassElement, List<Element>>(); 411 final Map<ClassElement, List<Element>> sortedClassMembers =
412 new Map<ClassElement, List<Element>>();
410 classMembers.forEach((classElement, members) { 413 classMembers.forEach((classElement, members) {
411 sortedClassMembers[classElement] = sortElements(members); 414 sortedClassMembers[classElement] = sortElements(members);
412 }); 415 });
413 416
414 if (outputAst) { 417 if (outputAst) {
415 // TODO(antonm): Ideally XML should be a separate backend. 418 // TODO(antonm): Ideally XML should be a separate backend.
416 // TODO(antonm): obey renames and minification, at least as an option. 419 // TODO(antonm): obey renames and minification, at least as an option.
417 StringBuffer sb = new StringBuffer(); 420 StringBuffer sb = new StringBuffer();
418 outputElement(element) { 421 outputElement(element) {
419 sb.write(element.parseNode(compiler).toDebugString()); 422 sb.write(element.parseNode(compiler).toDebugString());
420 } 423 }
421 424
422 // Emit XML for AST instead of the program. 425 // Emit XML for AST instead of the program.
423 for (final topLevel in sortedTopLevels) { 426 for (final topLevel in sortedTopLevels) {
424 if (topLevel.isClass && !emitNoMembersFor.contains(topLevel)) { 427 if (topLevel.isClass && !emitNoMembersFor.contains(topLevel)) {
425 // TODO(antonm): add some class info. 428 // TODO(antonm): add some class info.
426 sortedClassMembers[topLevel].forEach(outputElement); 429 sortedClassMembers[topLevel].forEach(outputElement);
427 } else { 430 } else {
428 outputElement(topLevel); 431 outputElement(topLevel);
429 } 432 }
430 } 433 }
431 compiler.assembledCode = '<Program>\n$sb</Program>\n'; 434 compiler.assembledCode = '<Program>\n$sb</Program>\n';
432 return; 435 return;
433 } 436 }
434 437
435 final topLevelNodes = <Node>[]; 438 final List<Node> topLevelNodes = <Node>[];
436 for (final element in sortedTopLevels) { 439 for (final element in sortedTopLevels) {
437 topLevelNodes.add(elementAsts[element].ast); 440 topLevelNodes.add(elementAsts[element].ast);
438 if (element.isClass && !element.isMixinApplication) { 441 if (element.isClass && !element.isMixinApplication) {
439 final members = <Node>[]; 442 final members = <Node>[];
440 for (final member in sortedClassMembers[element]) { 443 for (final member in sortedClassMembers[element]) {
441 members.add(elementAsts[member].ast); 444 members.add(elementAsts[member].ast);
442 } 445 }
443 memberNodes[elementAsts[element].ast] = members; 446 memberNodes[elementAsts[element].ast] = members;
444 } 447 }
445 } 448 }
446 449
447 if (useMirrorHelperLibrary) { 450 if (useMirrorHelperLibrary) {
448 mirrorRenamer.addRenames(renames, topLevelNodes, collector); 451 mirrorRenamer.addRenames(placeholderRenamer.renames,
452 topLevelNodes, collector);
449 } 453 }
450 454
451 final unparser = new EmitterUnparser(renames, stripTypes: forceStripTypes, 455 final EmitterUnparser unparser =
452 minify: compiler.enableMinification); 456 new EmitterUnparser(placeholderRenamer.renames,
453 emitCode(unparser, imports, topLevelNodes, memberNodes); 457 stripTypes: forceStripTypes,
454 String assembledCode = unparser.result; 458 minify: compiler.enableMinification);
455 compiler.outputProvider('', 'dart') 459 for (LibraryElement library in placeholderRenamer.platformImports) {
456 ..add(assembledCode) 460 if (library.isPlatformLibrary && !library.isInternalLibrary) {
457 ..close(); 461 unparser.unparseImportTag(library.canonicalUri.toString());
458 compiler.assembledCode = assembledCode; 462 }
463 }
464 for (int i = 0; i < sortedTopLevels.length; i++) {
465 Element element = sortedTopLevels[i];
466 Node node = topLevelNodes[i];
467 if (node is ClassNode) {
468 // TODO(smok): Filter out default constructors here.
469 unparser.unparseClassWithBody(node, memberNodes[node]);
470 } else {
471 unparser.unparse(node);
472 }
473 unparser.newline();
474 }
459 475
476 compiler.assembledCode = unparser.result;
477 compiler.outputProvider("", "dart")
478 ..add(compiler.assembledCode)
479 ..close();
460 // Output verbose info about size ratio of resulting bundle to all 480 // Output verbose info about size ratio of resulting bundle to all
461 // referenced non-platform sources. 481 // referenced non-platform sources.
462 logResultBundleSizeInfo(topLevelElements); 482 logResultBundleSizeInfo(topLevelElements);
463 } 483 }
464 484
465 void logResultBundleSizeInfo(Set<Element> topLevelElements) { 485 void logResultBundleSizeInfo(Set<Element> topLevelElements) {
466 Iterable<LibraryElement> referencedLibraries = 486 Iterable<LibraryElement> referencedLibraries =
467 compiler.libraryLoader.libraries.where(isUserLibrary); 487 compiler.libraryLoader.libraries.where(isUserLibrary);
468 // Sum total size of scripts in each referenced library. 488 // Sum total size of scripts in each referenced library.
469 int nonPlatformSize = 0; 489 int nonPlatformSize = 0;
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 } 694 }
675 695
676 Constant compileMetadata(MetadataAnnotation metadata, 696 Constant compileMetadata(MetadataAnnotation metadata,
677 Node node, 697 Node node,
678 TreeElements elements) { 698 TreeElements elements) {
679 return measure(() { 699 return measure(() {
680 return constantCompiler.compileMetadata(metadata, node, elements); 700 return constantCompiler.compileMetadata(metadata, node, elements);
681 }); 701 });
682 } 702 }
683 } 703 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698