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

Side by Side Diff: dart/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 12033003: Deferred (aka lazy) loading of static functions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address comments and use IsolateNatives.thisScript Created 7 years, 10 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 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
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 1637 matching lines...) Expand 10 before | Expand all | Expand 10 after
1711 Element member = element.lookupLocalMember(noSuchMethodName); 1712 Element member = element.lookupLocalMember(noSuchMethodName);
1712 if (member == null) continue; 1713 if (member == null) continue;
1713 if (noSuchMethodSelector.applies(member, compiler)) { 1714 if (noSuchMethodSelector.applies(member, compiler)) {
1714 nativeEmitter.handleNoSuchMethod = true; 1715 nativeEmitter.handleNoSuchMethod = true;
1715 break; 1716 break;
1716 } 1717 }
1717 } 1718 }
1718 } 1719 }
1719 1720
1720 for (ClassElement element in sortedClasses) { 1721 for (ClassElement element in sortedClasses) {
1722 if (isDeferred(element)) {
1723 warnNotImplemented(
1724 element,
1725 'Warning: deferred loading of classes is not implemented yet.');
1726 }
1721 generateClass(element, buffer); 1727 generateClass(element, buffer);
1722 } 1728 }
1723 1729
1724 // The closure class could have become necessary because of the generation 1730 // The closure class could have become necessary because of the generation
1725 // of stubs. 1731 // of stubs.
1726 ClassElement closureClass = compiler.closureClass; 1732 ClassElement closureClass = compiler.closureClass;
1727 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) { 1733 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) {
1728 generateClass(closureClass, buffer); 1734 generateClass(closureClass, buffer);
1729 } 1735 }
1730 } 1736 }
1731 1737
1732 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { 1738 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) {
1733 if (needsDefineClass) { 1739 if (needsDefineClass) {
1734 buffer.add("$finishClassesName($classesCollector)$N"); 1740 buffer.add("$finishClassesName($classesCollector)$N");
1735 // Reset the map. 1741 // Reset the map.
1736 buffer.add("$classesCollector$_=$_{}$N"); 1742 buffer.add("$classesCollector$_=$_{}$N");
1737 } 1743 }
1738 } 1744 }
1739 1745
1740 void emitStaticFunction(CodeBuffer buffer, 1746 void emitStaticFunction(CodeBuffer buffer,
1741 String name, 1747 String name,
1742 jsAst.Expression functionExpression) { 1748 jsAst.Expression functionExpression) {
1743 jsAst.Expression assignment = 1749 jsAst.Expression assignment =
1744 js[isolateProperties][name].assign(functionExpression); 1750 js[isolateProperties][name].assign(functionExpression);
1745 buffer.add(jsAst.prettyPrint(assignment, compiler)); 1751 buffer.add(jsAst.prettyPrint(assignment, compiler));
1746 buffer.add('$N$n'); 1752 buffer.add('$N$n');
1747 } 1753 }
1748 1754
1749 void emitStaticFunctions(CodeBuffer buffer) { 1755 void emitStaticFunctions(CodeBuffer eagerBuffer) {
1750 bool isStaticFunction(Element element) => 1756 bool isStaticFunction(Element element) =>
1751 !element.isInstanceMember() && !element.isField(); 1757 !element.isInstanceMember() && !element.isField();
1752 1758
1753 Iterable<Element> elements = 1759 Iterable<Element> elements =
1754 backend.generatedCode.keys.where(isStaticFunction); 1760 backend.generatedCode.keys.where(isStaticFunction);
1755 Set<Element> pendingElementsWithBailouts = 1761 Set<Element> pendingElementsWithBailouts =
1756 backend.generatedBailoutCode.keys 1762 backend.generatedBailoutCode.keys
1757 .where(isStaticFunction) 1763 .where(isStaticFunction)
1758 .toSet(); 1764 .toSet();
1759 1765
1760 for (Element element in Elements.sortedByPosition(elements)) { 1766 for (Element element in Elements.sortedByPosition(elements)) {
1767 CodeBuffer buffer = isDeferred(element) ? deferredBuffer : eagerBuffer;
1761 jsAst.Expression code = backend.generatedCode[element]; 1768 jsAst.Expression code = backend.generatedCode[element];
1762 emitStaticFunction(buffer, namer.getName(element), code); 1769 emitStaticFunction(buffer, namer.getName(element), code);
1763 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; 1770 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
1764 if (bailoutCode != null) { 1771 if (bailoutCode != null) {
1765 pendingElementsWithBailouts.remove(element); 1772 pendingElementsWithBailouts.remove(element);
1766 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); 1773 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
1767 } 1774 }
1768 } 1775 }
1769 1776
1770 // Is it possible the primary function was inlined but the bailout was not? 1777 // Is it possible the primary function was inlined but the bailout was not?
1771 for (Element element in 1778 for (Element element in
1772 Elements.sortedByPosition(pendingElementsWithBailouts)) { 1779 Elements.sortedByPosition(pendingElementsWithBailouts)) {
1780 CodeBuffer buffer = isDeferred(element) ? deferredBuffer : eagerBuffer;
1773 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; 1781 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
1774 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); 1782 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
1775 } 1783 }
1776 } 1784 }
1777 1785
1778 void emitStaticFunctionGetters(CodeBuffer buffer) { 1786 void emitStaticFunctionGetters(CodeBuffer buffer) {
1779 Set<FunctionElement> functionsNeedingGetter = 1787 Set<FunctionElement> functionsNeedingGetter =
1780 compiler.codegenWorld.staticFunctionsNeedingGetter; 1788 compiler.codegenWorld.staticFunctionsNeedingGetter;
1781 for (FunctionElement element in 1789 for (FunctionElement element in
1782 Elements.sortedByPosition(functionsNeedingGetter)) { 1790 Elements.sortedByPosition(functionsNeedingGetter)) {
1791 // TODO(ahe): Defer loading of these getters.
1792
1783 // The static function does not have the correct name. Since 1793 // The static function does not have the correct name. Since
1784 // [addParameterStubs] use the name to create its stubs we simply 1794 // [addParameterStubs] use the name to create its stubs we simply
1785 // create a fake element with the correct name. 1795 // create a fake element with the correct name.
1786 // Note: the callElement will not have any enclosingElement. 1796 // Note: the callElement will not have any enclosingElement.
1787 FunctionElement callElement = 1797 FunctionElement callElement =
1788 new ClosureInvocationElement(namer.closureInvocationSelectorName, 1798 new ClosureInvocationElement(namer.closureInvocationSelectorName,
1789 element); 1799 element);
1790 String staticName = namer.getName(element); 1800 String staticName = namer.getName(element);
1791 String invocationName = namer.instanceMethodName(callElement); 1801 String invocationName = namer.instanceMethodName(callElement);
1792 String fieldAccess = '$isolateProperties.$staticName'; 1802 String fieldAccess = '$isolateProperties.$staticName';
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after
2614 2624
2615 emitFinishIsolateConstructorInvocation(mainBuffer); 2625 emitFinishIsolateConstructorInvocation(mainBuffer);
2616 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' 2626 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_='
2617 '${_}new ${namer.isolateName}()$N'); 2627 '${_}new ${namer.isolateName}()$N');
2618 2628
2619 nativeEmitter.assembleCode(mainBuffer); 2629 nativeEmitter.assembleCode(mainBuffer);
2620 emitMain(mainBuffer); 2630 emitMain(mainBuffer);
2621 emitInitFunction(mainBuffer); 2631 emitInitFunction(mainBuffer);
2622 compiler.assembledCode = mainBuffer.getText(); 2632 compiler.assembledCode = mainBuffer.getText();
2623 2633
2624 if (generateSourceMap) { 2634 if (!deferredBuffer.isEmpty) {
2625 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); 2635 String code = deferredBuffer.getText();
2626 String sourceMap = buildSourceMap(mainBuffer, compiledFile); 2636 compiler.outputProvider('part', 'js')
2627 compiler.outputProvider('', 'js.map') 2637 ..add(code)
2628 ..add(sourceMap)
2629 ..close(); 2638 ..close();
2639 outputSourceMap(deferredBuffer, compiler.assembledCode, 'part');
2630 } 2640 }
2641
2642 outputSourceMap(mainBuffer, compiler.assembledCode, '');
2631 }); 2643 });
2632 return compiler.assembledCode; 2644 return compiler.assembledCode;
2633 } 2645 }
2634 2646
2635 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { 2647 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) {
2636 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); 2648 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder();
2637 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); 2649 buffer.forEachSourceLocation(sourceMapBuilder.addMapping);
2638 return sourceMapBuilder.build(compiledFile); 2650 return sourceMapBuilder.build(compiledFile);
2639 } 2651 }
2652
2653 void outputSourceMap(CodeBuffer buffer, String code, String name) {
2654 if (!generateSourceMap) return;
2655 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode);
2656 String sourceMap = buildSourceMap(mainBuffer, compiledFile);
2657 compiler.outputProvider(name, 'js.map')
2658 ..add(sourceMap)
2659 ..close();
2660 }
2661
2662 bool isDeferred(Element element) {
2663 return compiler.deferredLoadTask.isDeferred(element);
2664 }
2665
2666 // TODO(ahe): Remove this when deferred loading is fully implemented.
2667 void warnNotImplemented(Element element, String message) {
2668 compiler.reportMessage(compiler.spanFromSpannable(element),
2669 MessageKind.GENERIC.error({'text': message}),
2670 api.Diagnostic.WARNING);
2671 }
2640 } 2672 }
2641 2673
2642 const String GENERATED_BY = """ 2674 const String GENERATED_BY = """
2643 // Generated by dart2js, the Dart to JavaScript compiler. 2675 // Generated by dart2js, the Dart to JavaScript compiler.
2644 """; 2676 """;
2645 const String HOOKS_API_USAGE = """ 2677 const String HOOKS_API_USAGE = """
2646 // The code supports the following hooks: 2678 // The code supports the following hooks:
2647 // dartPrint(message) - if this function is defined it is called 2679 // dartPrint(message) - if this function is defined it is called
2648 // instead of the Dart [print] method. 2680 // instead of the Dart [print] method.
2649 // dartMainRunner(main) - if this function is defined, the Dart [main] 2681 // dartMainRunner(main) - if this function is defined, the Dart [main]
2650 // method will not be invoked directly. 2682 // method will not be invoked directly.
2651 // Instead, a closure that will invoke [main] is 2683 // Instead, a closure that will invoke [main] is
2652 // passed to [dartMainRunner]. 2684 // passed to [dartMainRunner].
2653 """; 2685 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698