| OLD | NEW |
| 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 { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 return new Block(rewriteNodeList(statements, builder.toLink())); | 115 return new Block(rewriteNodeList(statements, builder.toLink())); |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 | 118 |
| 119 class DartBackend extends Backend { | 119 class DartBackend extends Backend { |
| 120 final List<CompilerTask> tasks; | 120 final List<CompilerTask> tasks; |
| 121 final bool forceStripTypes; | 121 final bool forceStripTypes; |
| 122 final bool stripAsserts; | 122 final bool stripAsserts; |
| 123 // TODO(antonm): make available from command-line options. | 123 // TODO(antonm): make available from command-line options. |
| 124 final bool outputAst = false; | 124 final bool outputAst = false; |
| 125 final Map<Node, String> renames; |
| 126 final Map<LibraryElement, String> imports; |
| 127 final Map<ClassNode, List<Node>> memberNodes; |
| 128 // TODO(zarah) Maybe change this to a command-line option. |
| 129 // Right now, it is set by the tests. |
| 130 bool useMirrorHelperLibrary = false; |
| 125 | 131 |
| 126 Map<Element, TreeElements> get resolvedElements => | 132 Map<Element, TreeElements> get resolvedElements => |
| 127 compiler.enqueuer.resolution.resolvedElements; | 133 compiler.enqueuer.resolution.resolvedElements; |
| 128 | 134 |
| 129 /** | 135 /** |
| 130 * Tells whether it is safe to remove type declarations from variables, | 136 * Tells whether it is safe to remove type declarations from variables, |
| 131 * functions parameters. It becomes not safe if: | 137 * functions parameters. It becomes not safe if: |
| 132 * 1) TypeError is used somewhere in the code, | 138 * 1) TypeError is used somewhere in the code, |
| 133 * 2) The code has typedefs in right hand side of IS checks, | 139 * 2) The code has typedefs in right hand side of IS checks, |
| 134 * 3) The code has classes which extend typedefs, have type arguments typedefs | 140 * 3) The code has classes which extend typedefs, have type arguments typedefs |
| (...skipping 29 matching lines...) Expand all Loading... |
| 164 if (element.allSupertypes != null) { | 170 if (element.allSupertypes != null) { |
| 165 workQueue.addAll(element.allSupertypes.toList()); | 171 workQueue.addAll(element.allSupertypes.toList()); |
| 166 } | 172 } |
| 167 } | 173 } |
| 168 } | 174 } |
| 169 return true; | 175 return true; |
| 170 } | 176 } |
| 171 | 177 |
| 172 DartBackend(Compiler compiler, List<String> strips) | 178 DartBackend(Compiler compiler, List<String> strips) |
| 173 : tasks = <CompilerTask>[], | 179 : tasks = <CompilerTask>[], |
| 180 renames = new Map<Node, String>(), |
| 181 imports = new Map<LibraryElement, String>(), |
| 182 memberNodes = new Map<ClassNode, List<Node>>(), |
| 174 forceStripTypes = strips.indexOf('types') != -1, | 183 forceStripTypes = strips.indexOf('types') != -1, |
| 175 stripAsserts = strips.indexOf('asserts') != -1, | 184 stripAsserts = strips.indexOf('asserts') != -1, |
| 176 super(compiler); | 185 super(compiler); |
| 177 | 186 |
| 178 bool classNeedsRti(ClassElement cls) => false; | 187 bool classNeedsRti(ClassElement cls) => false; |
| 179 bool methodNeedsRti(FunctionElement function) => false; | 188 bool methodNeedsRti(FunctionElement function) => false; |
| 180 | 189 |
| 181 void enqueueHelpers(ResolutionEnqueuer world, TreeElements elements) { | 190 void enqueueHelpers(ResolutionEnqueuer world, TreeElements elements) { |
| 182 // Right now resolver doesn't always resolve interfaces needed | 191 // Right now resolver doesn't always resolve interfaces needed |
| 183 // for literals, so force them. TODO(antonm): fix in the resolver. | 192 // for literals, so force them. TODO(antonm): fix in the resolver. |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 // some unused identifier. | 397 // some unused identifier. |
| 389 collector.unresolvedNodes.add(synthesizedIdentifier); | 398 collector.unresolvedNodes.add(synthesizedIdentifier); |
| 390 makePlaceholders(element) { | 399 makePlaceholders(element) { |
| 391 collector.collect(element); | 400 collector.collect(element); |
| 392 if (element.isClass()) { | 401 if (element.isClass()) { |
| 393 classMembers[element].forEach(makePlaceholders); | 402 classMembers[element].forEach(makePlaceholders); |
| 394 } | 403 } |
| 395 } | 404 } |
| 396 topLevelElements.forEach(makePlaceholders); | 405 topLevelElements.forEach(makePlaceholders); |
| 397 // Create renames. | 406 // Create renames. |
| 398 Map<Node, String> renames = new Map<Node, String>(); | |
| 399 Map<LibraryElement, String> imports = new Map<LibraryElement, String>(); | |
| 400 bool shouldCutDeclarationTypes = forceStripTypes | 407 bool shouldCutDeclarationTypes = forceStripTypes |
| 401 || (compiler.enableMinification | 408 || (compiler.enableMinification |
| 402 && isSafeToRemoveTypeDeclarations(classMembers)); | 409 && isSafeToRemoveTypeDeclarations(classMembers)); |
| 403 renamePlaceholders( | 410 renamePlaceholders( |
| 404 compiler, collector, renames, imports, | 411 compiler, collector, renames, imports, |
| 405 fixedMemberNames, shouldCutDeclarationTypes); | 412 fixedMemberNames, shouldCutDeclarationTypes); |
| 406 | 413 |
| 407 // Sort elements. | 414 // Sort elements. |
| 408 final sortedTopLevels = sortElements(topLevelElements); | 415 final sortedTopLevels = sortElements(topLevelElements); |
| 409 final sortedClassMembers = new Map<ClassElement, List<Element>>(); | 416 final sortedClassMembers = new Map<ClassElement, List<Element>>(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 424 sortedClassMembers[topLevel].forEach(outputElement); | 431 sortedClassMembers[topLevel].forEach(outputElement); |
| 425 } else { | 432 } else { |
| 426 outputElement(topLevel); | 433 outputElement(topLevel); |
| 427 } | 434 } |
| 428 } | 435 } |
| 429 compiler.assembledCode = '<Program>\n$sb</Program>\n'; | 436 compiler.assembledCode = '<Program>\n$sb</Program>\n'; |
| 430 return; | 437 return; |
| 431 } | 438 } |
| 432 | 439 |
| 433 final topLevelNodes = <Node>[]; | 440 final topLevelNodes = <Node>[]; |
| 434 final memberNodes = new Map<ClassNode, List<Node>>(); | |
| 435 for (final element in sortedTopLevels) { | 441 for (final element in sortedTopLevels) { |
| 436 topLevelNodes.add(elementAsts[element].ast); | 442 topLevelNodes.add(elementAsts[element].ast); |
| 437 if (element.isClass() && !element.isMixinApplication) { | 443 if (element.isClass() && !element.isMixinApplication) { |
| 438 final members = <Node>[]; | 444 final members = <Node>[]; |
| 439 for (final member in sortedClassMembers[element]) { | 445 for (final member in sortedClassMembers[element]) { |
| 440 members.add(elementAsts[member].ast); | 446 members.add(elementAsts[member].ast); |
| 441 } | 447 } |
| 442 memberNodes[elementAsts[element].ast] = members; | 448 memberNodes[elementAsts[element].ast] = members; |
| 443 } | 449 } |
| 444 } | 450 } |
| 445 | 451 |
| 452 if (useMirrorHelperLibrary && compiler.mirrorsLibrary != null) { |
| 453 MirrorRenamer.addMirrorHelperImport(imports); |
| 454 } |
| 455 |
| 446 final unparser = new EmitterUnparser(renames); | 456 final unparser = new EmitterUnparser(renames); |
| 447 emitCode(unparser, imports, topLevelNodes, memberNodes); | 457 emitCode(unparser, imports, topLevelNodes, memberNodes); |
| 448 compiler.assembledCode = unparser.result; | 458 compiler.assembledCode = unparser.result; |
| 449 | 459 |
| 450 // Output verbose info about size ratio of resulting bundle to all | 460 // Output verbose info about size ratio of resulting bundle to all |
| 451 // referenced non-platform sources. | 461 // referenced non-platform sources. |
| 452 logResultBundleSizeInfo(topLevelElements); | 462 logResultBundleSizeInfo(topLevelElements); |
| 453 } | 463 } |
| 454 | 464 |
| 455 void logResultBundleSizeInfo(Set<Element> topLevelElements) { | 465 void logResultBundleSizeInfo(Set<Element> topLevelElements) { |
| 456 Iterable<LibraryElement> referencedLibraries = | 466 Iterable<LibraryElement> referencedLibraries = |
| 457 compiler.libraries.values.where(isUserLibrary); | 467 compiler.libraries.values.where(isUserLibrary); |
| 458 // Sum total size of scripts in each referenced library. | 468 // Sum total size of scripts in each referenced library. |
| 459 int nonPlatformSize = 0; | 469 int nonPlatformSize = 0; |
| 460 for (LibraryElement lib in referencedLibraries) { | 470 for (LibraryElement lib in referencedLibraries) { |
| 461 for (CompilationUnitElement compilationUnit in lib.compilationUnits) { | 471 for (CompilationUnitElement compilationUnit in lib.compilationUnits) { |
| 462 nonPlatformSize += compilationUnit.script.text.length; | 472 nonPlatformSize += compilationUnit.script.text.length; |
| 463 } | 473 } |
| 464 } | 474 } |
| 465 int percentage = compiler.assembledCode.length * 100 ~/ nonPlatformSize; | 475 int percentage = compiler.assembledCode.length * 100 ~/ nonPlatformSize; |
| 466 log('Total used non-platform files size: ${nonPlatformSize} bytes, ' | 476 log('Total used non-platform files size: ${nonPlatformSize} bytes, ' |
| 467 'bundle size: ${compiler.assembledCode.length} bytes (${percentage}%)'); | 477 'bundle size: ${compiler.assembledCode.length} bytes (${percentage}%)'); |
| 468 } | 478 } |
| 469 | 479 |
| 470 log(String message) => compiler.log('[DartBackend] $message'); | 480 log(String message) => compiler.log('[DartBackend] $message'); |
| 481 |
| 482 void registerStaticSend(Element element, Node node) { |
| 483 if (useMirrorHelperLibrary && compiler.mirrorsLibrary != null) { |
| 484 MirrorRenamer.handleStaticSend(renames, element, node, compiler); |
| 485 } |
| 486 } |
| 471 } | 487 } |
| 472 | 488 |
| 473 class EmitterUnparser extends Unparser { | 489 class EmitterUnparser extends Unparser { |
| 474 final Map<Node, String> renames; | 490 final Map<Node, String> renames; |
| 475 | 491 |
| 476 EmitterUnparser(this.renames); | 492 EmitterUnparser(this.renames); |
| 477 | 493 |
| 478 visit(Node node) { | 494 visit(Node node) { |
| 479 if (node != null && renames.containsKey(node)) { | 495 if (node != null && renames.containsKey(node)) { |
| 480 sb.write(renames[node]); | 496 sb.write(renames[node]); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 } | 562 } |
| 547 | 563 |
| 548 compareElements(e0, e1) { | 564 compareElements(e0, e1) { |
| 549 int result = compareBy((e) => e.getLibrary().canonicalUri.toString())(e0, e1); | 565 int result = compareBy((e) => e.getLibrary().canonicalUri.toString())(e0, e1); |
| 550 if (result != 0) return result; | 566 if (result != 0) return result; |
| 551 return compareBy((e) => e.position().charOffset)(e0, e1); | 567 return compareBy((e) => e.position().charOffset)(e0, e1); |
| 552 } | 568 } |
| 553 | 569 |
| 554 List<Element> sortElements(Iterable<Element> elements) => | 570 List<Element> sortElements(Iterable<Element> elements) => |
| 555 sorted(elements, compareElements); | 571 sorted(elements, compareElements); |
| OLD | NEW |