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 |