Chromium Code Reviews| 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 js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 class CodeEmitterTask extends CompilerTask { | 54 class CodeEmitterTask extends CompilerTask { |
| 55 bool needsInheritFunction = false; | 55 bool needsInheritFunction = false; |
| 56 bool needsDefineClass = false; | 56 bool needsDefineClass = false; |
| 57 bool needsClosureClass = false; | 57 bool needsClosureClass = false; |
| 58 bool needsLazyInitializer = false; | 58 bool needsLazyInitializer = false; |
| 59 final Namer namer; | 59 final Namer namer; |
| 60 ConstantEmitter constantEmitter; | 60 ConstantEmitter constantEmitter; |
| 61 NativeEmitter nativeEmitter; | 61 NativeEmitter nativeEmitter; |
| 62 CodeBuffer boundClosureBuffer; | 62 CodeBuffer boundClosureBuffer; |
| 63 CodeBuffer mainBuffer; | 63 CodeBuffer mainBuffer; |
| 64 final CodeBuffer deferredBuffer = new CodeBuffer(); | |
| 64 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 65 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
| 65 well as in the generated code. */ | 66 well as in the generated code. */ |
| 66 String isolateProperties; | 67 String isolateProperties; |
| 67 String classesCollector; | 68 String classesCollector; |
| 68 Set<ClassElement> neededClasses; | 69 Set<ClassElement> neededClasses; |
| 69 // TODO(ngeoffray): remove this field. | 70 // TODO(ngeoffray): remove this field. |
| 70 Set<ClassElement> instantiatedClasses; | 71 Set<ClassElement> instantiatedClasses; |
| 71 | 72 |
| 72 JavaScriptBackend get backend => compiler.backend; | 73 JavaScriptBackend get backend => compiler.backend; |
| 73 | 74 |
| (...skipping 1631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1705 Element member = element.lookupLocalMember(noSuchMethodName); | 1706 Element member = element.lookupLocalMember(noSuchMethodName); |
| 1706 if (member == null) continue; | 1707 if (member == null) continue; |
| 1707 if (noSuchMethodSelector.applies(member, compiler)) { | 1708 if (noSuchMethodSelector.applies(member, compiler)) { |
| 1708 nativeEmitter.handleNoSuchMethod = true; | 1709 nativeEmitter.handleNoSuchMethod = true; |
| 1709 break; | 1710 break; |
| 1710 } | 1711 } |
| 1711 } | 1712 } |
| 1712 } | 1713 } |
| 1713 | 1714 |
| 1714 for (ClassElement element in sortedClasses) { | 1715 for (ClassElement element in sortedClasses) { |
| 1716 if (isDeferred(element)) { | |
| 1717 warnNotImplemented( | |
| 1718 element, | |
| 1719 'Warning: deferred loading of classes is not implemented yet.'); | |
| 1720 } | |
| 1715 generateClass(element, buffer); | 1721 generateClass(element, buffer); |
| 1716 } | 1722 } |
| 1717 | 1723 |
| 1718 // The closure class could have become necessary because of the generation | 1724 // The closure class could have become necessary because of the generation |
| 1719 // of stubs. | 1725 // of stubs. |
| 1720 ClassElement closureClass = compiler.closureClass; | 1726 ClassElement closureClass = compiler.closureClass; |
| 1721 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) { | 1727 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) { |
| 1722 generateClass(closureClass, buffer); | 1728 generateClass(closureClass, buffer); |
| 1723 } | 1729 } |
| 1724 } | 1730 } |
| 1725 | 1731 |
| 1726 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { | 1732 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { |
| 1727 if (needsDefineClass) { | 1733 if (needsDefineClass) { |
| 1728 buffer.add("$finishClassesName($classesCollector)$N"); | 1734 buffer.add("$finishClassesName($classesCollector)$N"); |
| 1729 // Reset the map. | 1735 // Reset the map. |
| 1730 buffer.add("$classesCollector$_=$_{}$N"); | 1736 buffer.add("$classesCollector$_=$_{}$N"); |
| 1731 } | 1737 } |
| 1732 } | 1738 } |
| 1733 | 1739 |
| 1734 void emitStaticFunction(CodeBuffer buffer, | 1740 void emitStaticFunction(CodeBuffer buffer, |
| 1735 String name, | 1741 String name, |
| 1736 jsAst.Expression functionExpression) { | 1742 jsAst.Expression functionExpression) { |
| 1737 jsAst.Expression assignment = | 1743 jsAst.Expression assignment = |
| 1738 js[isolateProperties][name].assign(functionExpression); | 1744 js[isolateProperties][name].assign(functionExpression); |
| 1739 buffer.add(jsAst.prettyPrint(assignment, compiler)); | 1745 buffer.add(jsAst.prettyPrint(assignment, compiler)); |
| 1740 buffer.add('$N$n'); | 1746 buffer.add('$N$n'); |
| 1741 } | 1747 } |
| 1742 | 1748 |
| 1743 void emitStaticFunctions(CodeBuffer buffer) { | 1749 void emitStaticFunctions(CodeBuffer eagerBuffer) { |
| 1744 bool isStaticFunction(Element element) => | 1750 bool isStaticFunction(Element element) => |
| 1745 !element.isInstanceMember() && !element.isField(); | 1751 !element.isInstanceMember() && !element.isField(); |
| 1746 | 1752 |
| 1747 Iterable<Element> elements = | 1753 Iterable<Element> elements = |
| 1748 backend.generatedCode.keys.where(isStaticFunction); | 1754 backend.generatedCode.keys.where(isStaticFunction); |
| 1749 Set<Element> pendingElementsWithBailouts = | 1755 Set<Element> pendingElementsWithBailouts = |
| 1750 backend.generatedBailoutCode.keys | 1756 backend.generatedBailoutCode.keys |
| 1751 .where(isStaticFunction) | 1757 .where(isStaticFunction) |
| 1752 .toSet(); | 1758 .toSet(); |
| 1753 | 1759 |
| 1754 for (Element element in Elements.sortedByPosition(elements)) { | 1760 for (Element element in Elements.sortedByPosition(elements)) { |
| 1761 CodeBuffer buffer = isDeferred(element) ? deferredBuffer : eagerBuffer; | |
| 1755 jsAst.Expression code = backend.generatedCode[element]; | 1762 jsAst.Expression code = backend.generatedCode[element]; |
| 1756 emitStaticFunction(buffer, namer.getName(element), code); | 1763 emitStaticFunction(buffer, namer.getName(element), code); |
| 1757 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; | 1764 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; |
| 1758 if (bailoutCode != null) { | 1765 if (bailoutCode != null) { |
| 1759 pendingElementsWithBailouts.remove(element); | 1766 pendingElementsWithBailouts.remove(element); |
| 1760 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); | 1767 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); |
| 1761 } | 1768 } |
| 1762 } | 1769 } |
| 1763 | 1770 |
| 1764 // Is it possible the primary function was inlined but the bailout was not? | 1771 // Is it possible the primary function was inlined but the bailout was not? |
| 1765 for (Element element in | 1772 for (Element element in |
| 1766 Elements.sortedByPosition(pendingElementsWithBailouts)) { | 1773 Elements.sortedByPosition(pendingElementsWithBailouts)) { |
| 1774 CodeBuffer buffer = isDeferred(element) ? deferredBuffer : eagerBuffer; | |
| 1767 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; | 1775 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; |
| 1768 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); | 1776 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); |
| 1769 } | 1777 } |
| 1770 } | 1778 } |
| 1771 | 1779 |
| 1772 void emitStaticFunctionGetters(CodeBuffer buffer) { | 1780 void emitStaticFunctionGetters(CodeBuffer buffer) { |
| 1773 Set<FunctionElement> functionsNeedingGetter = | 1781 Set<FunctionElement> functionsNeedingGetter = |
| 1774 compiler.codegenWorld.staticFunctionsNeedingGetter; | 1782 compiler.codegenWorld.staticFunctionsNeedingGetter; |
| 1775 for (FunctionElement element in | 1783 for (FunctionElement element in |
| 1776 Elements.sortedByPosition(functionsNeedingGetter)) { | 1784 Elements.sortedByPosition(functionsNeedingGetter)) { |
| 1785 // TODO(ahe): Defer loading of these getters. | |
|
ngeoffray
2013/02/19 10:04:57
warnNotImplemented?
ahe
2013/02/19 11:10:36
The overhead is small, and I can't give a location
| |
| 1786 | |
| 1777 // The static function does not have the correct name. Since | 1787 // The static function does not have the correct name. Since |
| 1778 // [addParameterStubs] use the name to create its stubs we simply | 1788 // [addParameterStubs] use the name to create its stubs we simply |
| 1779 // create a fake element with the correct name. | 1789 // create a fake element with the correct name. |
| 1780 // Note: the callElement will not have any enclosingElement. | 1790 // Note: the callElement will not have any enclosingElement. |
| 1781 FunctionElement callElement = | 1791 FunctionElement callElement = |
| 1782 new ClosureInvocationElement(namer.closureInvocationSelectorName, | 1792 new ClosureInvocationElement(namer.closureInvocationSelectorName, |
| 1783 element); | 1793 element); |
| 1784 String staticName = namer.getName(element); | 1794 String staticName = namer.getName(element); |
| 1785 String invocationName = namer.instanceMethodName(callElement); | 1795 String invocationName = namer.instanceMethodName(callElement); |
| 1786 String fieldAccess = '$isolateProperties.$staticName'; | 1796 String fieldAccess = '$isolateProperties.$staticName'; |
| (...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2608 | 2618 |
| 2609 emitFinishIsolateConstructorInvocation(mainBuffer); | 2619 emitFinishIsolateConstructorInvocation(mainBuffer); |
| 2610 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' | 2620 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' |
| 2611 '${_}new ${namer.isolateName}()$N'); | 2621 '${_}new ${namer.isolateName}()$N'); |
| 2612 | 2622 |
| 2613 nativeEmitter.assembleCode(mainBuffer); | 2623 nativeEmitter.assembleCode(mainBuffer); |
| 2614 emitMain(mainBuffer); | 2624 emitMain(mainBuffer); |
| 2615 emitInitFunction(mainBuffer); | 2625 emitInitFunction(mainBuffer); |
| 2616 compiler.assembledCode = mainBuffer.getText(); | 2626 compiler.assembledCode = mainBuffer.getText(); |
| 2617 | 2627 |
| 2618 if (generateSourceMap) { | 2628 if (!deferredBuffer.isEmpty) { |
| 2619 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); | 2629 String code = deferredBuffer.getText(); |
| 2620 String sourceMap = buildSourceMap(mainBuffer, compiledFile); | 2630 compiler.outputProvider('part', 'js') |
| 2621 compiler.outputProvider('', 'js.map') | 2631 ..add(code) |
| 2622 ..add(sourceMap) | |
| 2623 ..close(); | 2632 ..close(); |
| 2633 outputSourceMap(deferredBuffer, compiler.assembledCode, 'part'); | |
| 2624 } | 2634 } |
| 2635 | |
| 2636 outputSourceMap(mainBuffer, compiler.assembledCode, ''); | |
| 2625 }); | 2637 }); |
| 2626 return compiler.assembledCode; | 2638 return compiler.assembledCode; |
| 2627 } | 2639 } |
| 2628 | 2640 |
| 2629 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { | 2641 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { |
| 2630 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); | 2642 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); |
| 2631 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); | 2643 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); |
| 2632 return sourceMapBuilder.build(compiledFile); | 2644 return sourceMapBuilder.build(compiledFile); |
| 2633 } | 2645 } |
| 2646 | |
| 2647 void outputSourceMap(CodeBuffer buffer, String code, String name) { | |
| 2648 if (!generateSourceMap) return; | |
| 2649 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); | |
| 2650 String sourceMap = buildSourceMap(mainBuffer, compiledFile); | |
| 2651 compiler.outputProvider(name, 'js.map') | |
| 2652 ..add(sourceMap) | |
| 2653 ..close(); | |
| 2654 } | |
| 2655 | |
| 2656 bool isDeferred(Element element) { | |
| 2657 return compiler.deferredLoadTask.isDeferred(element); | |
| 2658 } | |
| 2659 | |
| 2660 // TODO(ahe): Remove this when deferred loading is fully implemented. | |
| 2661 void warnNotImplemented(Element element, String message) { | |
| 2662 compiler.reportMessage(compiler.spanFromSpannable(element), | |
| 2663 MessageKind.GENERIC.error({'text': message}), | |
| 2664 api.Diagnostic.WARNING); | |
| 2665 } | |
| 2634 } | 2666 } |
| 2635 | 2667 |
| 2636 const String GENERATED_BY = """ | 2668 const String GENERATED_BY = """ |
| 2637 // Generated by dart2js, the Dart to JavaScript compiler. | 2669 // Generated by dart2js, the Dart to JavaScript compiler. |
| 2638 """; | 2670 """; |
| 2639 const String HOOKS_API_USAGE = """ | 2671 const String HOOKS_API_USAGE = """ |
| 2640 // The code supports the following hooks: | 2672 // The code supports the following hooks: |
| 2641 // dartPrint(message) - if this function is defined it is called | 2673 // dartPrint(message) - if this function is defined it is called |
| 2642 // instead of the Dart [print] method. | 2674 // instead of the Dart [print] method. |
| 2643 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2675 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2644 // method will not be invoked directly. | 2676 // method will not be invoked directly. |
| 2645 // Instead, a closure that will invoke [main] is | 2677 // Instead, a closure that will invoke [main] is |
| 2646 // passed to [dartMainRunner]. | 2678 // passed to [dartMainRunner]. |
| 2647 """; | 2679 """; |
| OLD | NEW |