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 dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 const USE_NEW_EMITTER = const bool.fromEnvironment("dart2js.use.new.emitter"); | 7 const USE_NEW_EMITTER = const bool.fromEnvironment("dart2js.use.new.emitter"); |
8 | 8 |
9 /** | 9 /** |
10 * Generates the code for all used classes in the program. Static fields (even | 10 * Generates the code for all used classes in the program. Static fields (even |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
80 | 80 |
81 /** | 81 /** |
82 * List of expressions and statements that will be included in the | 82 * List of expressions and statements that will be included in the |
83 * precompiled function. | 83 * precompiled function. |
84 * | 84 * |
85 * To save space, dart2js normally generates constructors and accessors | 85 * To save space, dart2js normally generates constructors and accessors |
86 * dynamically. This doesn't work in CSP mode, and may impact startup time | 86 * dynamically. This doesn't work in CSP mode, and may impact startup time |
87 * negatively. So dart2js will emit these functions to a separate file that | 87 * negatively. So dart2js will emit these functions to a separate file that |
88 * can be optionally included to support CSP mode or for faster startup. | 88 * can be optionally included to support CSP mode or for faster startup. |
89 */ | 89 */ |
90 List<jsAst.Node> precompiledFunction = <jsAst.Node>[]; | 90 Map<OutputUnit, List<jsAst.Node>> _precompiledFunctions = |
91 new Map<OutputUnit, List<jsAst.Node>>(); | |
91 | 92 |
92 List<jsAst.Expression> precompiledConstructorNames = <jsAst.Expression>[]; | 93 Map<OutputUnit, List<jsAst.Expression>> _precompiledConstructorNames = |
94 new Map<OutputUnit, List<jsAst.Expression>>(); | |
93 | 95 |
94 // True if Isolate.makeConstantList is needed. | 96 // True if Isolate.makeConstantList is needed. |
95 bool hasMakeConstantList = false; | 97 bool hasMakeConstantList = false; |
96 | 98 |
97 /** | 99 /** |
98 * Accumulate properties for classes and libraries, describing their | 100 * Accumulate properties for classes and libraries, describing their |
99 * static/top-level members. | 101 * static/top-level members. |
100 * Later, these members are emitted when the class or library is emitted. | 102 * Later, these members are emitted when the class or library is emitted. |
101 * | 103 * |
102 * For supporting deferred loading we keep one list per output unit. | 104 * For supporting deferred loading we keep one list per output unit. |
(...skipping 19 matching lines...) Expand all Loading... | |
122 classEmitter.task = this; | 124 classEmitter.task = this; |
123 nsmEmitter.task = this; | 125 nsmEmitter.task = this; |
124 typeTestEmitter.task = this; | 126 typeTestEmitter.task = this; |
125 interceptorEmitter.task = this; | 127 interceptorEmitter.task = this; |
126 metadataEmitter.task = this; | 128 metadataEmitter.task = this; |
127 // TODO(18886): Remove this call (and the show in the import) once the | 129 // TODO(18886): Remove this call (and the show in the import) once the |
128 // memory-leak in the VM is fixed. | 130 // memory-leak in the VM is fixed. |
129 templateManager.clear(); | 131 templateManager.clear(); |
130 } | 132 } |
131 | 133 |
134 List<jsAst.Node> precompiledFunction(OutputUnit outputUnit) { | |
floitsch
2014/09/12 17:00:18
precompiledFunctionsFor
sigurdm
2014/09/15 13:10:48
Done.
| |
135 return _precompiledFunctions | |
136 .putIfAbsent(outputUnit, () => new List<jsAst.Node>()); | |
137 } | |
138 | |
139 List<jsAst.Expression> precompiledConstructorNames(OutputUnit outputUnit) { | |
floitsch
2014/09/12 17:00:17
precompiledConstructorNamesFor
sigurdm
2014/09/15 13:10:48
Done.
| |
140 return _precompiledConstructorNames | |
141 .putIfAbsent(outputUnit, () => new List<jsAst.Expression>()); | |
142 } | |
143 | |
132 void addComment(String comment, CodeBuffer buffer) { | 144 void addComment(String comment, CodeBuffer buffer) { |
133 buffer.write(jsAst.prettyPrint(js.comment(comment), compiler)); | 145 buffer.write(jsAst.prettyPrint(js.comment(comment), compiler)); |
134 } | 146 } |
135 | 147 |
136 jsAst.Expression constantReference(Constant value) { | 148 jsAst.Expression constantReference(Constant value) { |
137 return constantEmitter.reference(value); | 149 return constantEmitter.reference(value); |
138 } | 150 } |
139 | 151 |
140 jsAst.Expression constantInitializerExpression(Constant value) { | 152 jsAst.Expression constantInitializerExpression(Constant value) { |
141 return constantEmitter.initializationExpression(value); | 153 return constantEmitter.initializationExpression(value); |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
816 throw compiler.internalError(element, | 828 throw compiler.internalError(element, |
817 'Do not know how to reflect on this $element.'); | 829 'Do not know how to reflect on this $element.'); |
818 } | 830 } |
819 | 831 |
820 String namedParametersAsReflectionNames(Selector selector) { | 832 String namedParametersAsReflectionNames(Selector selector) { |
821 if (selector.getOrderedNamedArguments().isEmpty) return ''; | 833 if (selector.getOrderedNamedArguments().isEmpty) return ''; |
822 String names = selector.getOrderedNamedArguments().join(':'); | 834 String names = selector.getOrderedNamedArguments().join(':'); |
823 return ':$names'; | 835 return ':$names'; |
824 } | 836 } |
825 | 837 |
826 jsAst.FunctionDeclaration buildPrecompiledFunction() { | 838 jsAst.FunctionDeclaration buildPrecompiledFunction(OutputUnit outputUnit) { |
827 // TODO(ahe): Compute a hash code. | 839 // TODO(ahe): Compute a hash code. |
828 return js.statement(''' | 840 return js.statement(''' |
829 function dart_precompiled(\$collectedClasses) { | 841 function dart_precompiled(\$collectedClasses) { |
830 var \$desc; | 842 var \$desc; |
831 #; | 843 #; |
832 return #; | 844 return #; |
833 }''', [ | 845 }''', [ |
834 precompiledFunction, | 846 precompiledFunction(outputUnit), |
835 new jsAst.ArrayInitializer.from(precompiledConstructorNames)]); | 847 new jsAst.ArrayInitializer.from( |
848 precompiledConstructorNames(outputUnit))]); | |
836 } | 849 } |
837 | 850 |
838 void generateClass(ClassElement classElement, ClassBuilder properties) { | 851 void generateClass(ClassElement classElement, ClassBuilder properties) { |
839 compiler.withCurrentElement(classElement, () { | 852 compiler.withCurrentElement(classElement, () { |
840 if (compiler.hasIncrementalSupport) { | 853 if (compiler.hasIncrementalSupport) { |
841 ClassBuilder builder = | 854 ClassBuilder builder = |
842 cachedClassBuilders.putIfAbsent(classElement, () { | 855 cachedClassBuilders.putIfAbsent(classElement, () { |
843 ClassBuilder builder = new ClassBuilder(classElement, namer); | 856 ClassBuilder builder = new ClassBuilder(classElement, namer); |
844 classEmitter.generateClass( | 857 classEmitter.generateClass( |
845 classElement, builder, additionalProperties[classElement]); | 858 classElement, builder, additionalProperties[classElement]); |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1426 ..write(namer.globalObjectFor(library)) | 1439 ..write(namer.globalObjectFor(library)) |
1427 ..write(',$_') | 1440 ..write(',$_') |
1428 ..write(jsAst.prettyPrint(initializers, | 1441 ..write(jsAst.prettyPrint(initializers, |
1429 compiler, | 1442 compiler, |
1430 monitor: compiler.dumpInfoTask)) | 1443 monitor: compiler.dumpInfoTask)) |
1431 ..write(library == compiler.mainApp ? ',${n}1' : "") | 1444 ..write(library == compiler.mainApp ? ',${n}1' : "") |
1432 ..write('],$n'); | 1445 ..write('],$n'); |
1433 } | 1446 } |
1434 } | 1447 } |
1435 | 1448 |
1436 void emitPrecompiledConstructor(String constructorName, | 1449 void emitPrecompiledConstructor(OutputUnit outputUnit, |
1450 String constructorName, | |
1437 jsAst.Expression constructorAst) { | 1451 jsAst.Expression constructorAst) { |
1438 precompiledFunction.add( | 1452 precompiledFunction(outputUnit).add( |
1439 new jsAst.FunctionDeclaration( | 1453 new jsAst.FunctionDeclaration( |
1440 new jsAst.VariableDeclaration(constructorName), constructorAst)); | 1454 new jsAst.VariableDeclaration(constructorName), constructorAst)); |
1441 precompiledFunction.add( | 1455 precompiledFunction(outputUnit).add( |
1442 js.statement(r'''{ | 1456 js.statement(r'''{ |
1443 #.builtin$cls = #; | 1457 #.builtin$cls = #; |
1444 if (!"name" in #) | 1458 if (!"name" in #) |
1445 #.name = #; | 1459 #.name = #; |
1446 $desc=$collectedClasses.#; | 1460 $desc=$collectedClasses.#; |
1447 if ($desc instanceof Array) $desc = $desc[1]; | 1461 if ($desc instanceof Array) $desc = $desc[1]; |
1448 #.prototype = $desc; | 1462 #.prototype = $desc; |
1449 }''', | 1463 }''', |
1450 [ constructorName, js.string(constructorName), | 1464 [ constructorName, js.string(constructorName), |
1451 constructorName, | 1465 constructorName, |
1452 constructorName, js.string(constructorName), | 1466 constructorName, js.string(constructorName), |
1453 constructorName, | 1467 constructorName, |
1454 constructorName | 1468 constructorName |
1455 ])); | 1469 ])); |
1456 | 1470 |
1457 precompiledConstructorNames.add(js('#', constructorName)); | 1471 precompiledConstructorNames(outputUnit).add(js('#', constructorName)); |
1458 } | 1472 } |
1459 | 1473 |
1460 void assembleProgram() { | 1474 void assembleProgram() { |
1461 measure(() { | 1475 measure(() { |
1462 invalidateCaches(); | 1476 invalidateCaches(); |
1463 | 1477 |
1464 // Compute the required type checks to know which classes need a | 1478 // Compute the required type checks to know which classes need a |
1465 // 'is$' method. | 1479 // 'is$' method. |
1466 typeTestEmitter.computeRequiredTypeChecks(); | 1480 typeTestEmitter.computeRequiredTypeChecks(); |
1467 | 1481 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1614 js.string(typeReference)); | 1628 js.string(typeReference)); |
1615 jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]); | 1629 jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]); |
1616 String mangledName = namer.getNameX(typedef); | 1630 String mangledName = namer.getNameX(typedef); |
1617 String reflectionName = getReflectionName(typedef, mangledName); | 1631 String reflectionName = getReflectionName(typedef, mangledName); |
1618 getElementDescriptorForOutputUnit(library, mainUnit) | 1632 getElementDescriptorForOutputUnit(library, mainUnit) |
1619 ..addProperty(mangledName, declaration) | 1633 ..addProperty(mangledName, declaration) |
1620 ..addProperty("+$reflectionName", js.string('')); | 1634 ..addProperty("+$reflectionName", js.string('')); |
1621 // Also emit a trivial constructor for CSP mode. | 1635 // Also emit a trivial constructor for CSP mode. |
1622 String constructorName = mangledName; | 1636 String constructorName = mangledName; |
1623 jsAst.Expression constructorAst = js('function() {}'); | 1637 jsAst.Expression constructorAst = js('function() {}'); |
1624 emitPrecompiledConstructor(constructorName, constructorAst); | 1638 emitPrecompiledConstructor(mainOutputUnit, |
1639 constructorName, | |
1640 constructorAst); | |
1625 } | 1641 } |
1626 | 1642 |
1627 if (!mangledFieldNames.isEmpty) { | 1643 if (!mangledFieldNames.isEmpty) { |
1628 var keys = mangledFieldNames.keys.toList(); | 1644 var keys = mangledFieldNames.keys.toList(); |
1629 keys.sort(); | 1645 keys.sort(); |
1630 var properties = []; | 1646 var properties = []; |
1631 for (String key in keys) { | 1647 for (String key in keys) { |
1632 var value = js.string('${mangledFieldNames[key]}'); | 1648 var value = js.string('${mangledFieldNames[key]}'); |
1633 properties.add(new jsAst.Property(js.string(key), value)); | 1649 properties.add(new jsAst.Property(js.string(key), value)); |
1634 } | 1650 } |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1783 if (typeof print === "function") { | 1799 if (typeof print === "function") { |
1784 print("Size of $object: " | 1800 print("Size of $object: " |
1785 + String(Object.getOwnPropertyNames($object).length) | 1801 + String(Object.getOwnPropertyNames($object).length) |
1786 + ", fast properties " + HasFastProperties($object)); | 1802 + ", fast properties " + HasFastProperties($object)); |
1787 } | 1803 } |
1788 '''); | 1804 '''); |
1789 } | 1805 } |
1790 } | 1806 } |
1791 | 1807 |
1792 jsAst.FunctionDeclaration precompiledFunctionAst = | 1808 jsAst.FunctionDeclaration precompiledFunctionAst = |
1793 buildPrecompiledFunction(); | 1809 buildPrecompiledFunction(mainOutputUnit); |
1794 emitInitFunction(mainBuffer); | 1810 emitInitFunction(mainBuffer); |
1795 emitMain(mainBuffer); | 1811 emitMain(mainBuffer); |
1796 mainBuffer.add('})()\n'); | 1812 mainBuffer.add('})()\n'); |
1797 | 1813 |
1798 if (compiler.useContentSecurityPolicy) { | 1814 if (compiler.useContentSecurityPolicy) { |
1799 mainBuffer.write( | 1815 mainBuffer.write( |
1800 jsAst.prettyPrint( | 1816 jsAst.prettyPrint( |
1801 precompiledFunctionAst, compiler, | 1817 precompiledFunctionAst, compiler, |
1802 monitor: compiler.dumpInfoTask, | 1818 monitor: compiler.dumpInfoTask, |
1803 allowVariableMinification: false).getText()); | 1819 allowVariableMinification: false).getText()); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2020 | 2036 |
2021 typeTestEmitter.emitRuntimeTypeSupport(outputBuffer, outputUnit); | 2037 typeTestEmitter.emitRuntimeTypeSupport(outputBuffer, outputUnit); |
2022 | 2038 |
2023 emitCompileTimeConstants(outputBuffer, outputUnit); | 2039 emitCompileTimeConstants(outputBuffer, outputUnit); |
2024 outputBuffer.write('}$N'); | 2040 outputBuffer.write('}$N'); |
2025 String code = outputBuffer.getText(); | 2041 String code = outputBuffer.getText(); |
2026 | 2042 |
2027 // Make a unique hash of the code (before the sourcemaps are added) | 2043 // Make a unique hash of the code (before the sourcemaps are added) |
2028 // This will be used to retrieve the initializing function from the global | 2044 // This will be used to retrieve the initializing function from the global |
2029 // variable. | 2045 // variable. |
2030 String hash = hashOfString(code); | 2046 String hash = hashOfString(code); |
floitsch
2014/09/12 17:00:17
Can't you do the hash after the cspcode?
sigurdm
2014/09/15 13:10:48
My thinking was that the csp-code follows determin
| |
2031 | 2047 |
2048 CodeBuffer cspCode = new CodeBuffer(); | |
2049 if (compiler.useContentSecurityPolicy) { | |
2050 jsAst.FunctionDeclaration precompiledFunctionAst = | |
2051 buildPrecompiledFunction(outputUnit); | |
2052 | |
2053 cspCode.write( | |
2054 jsAst.prettyPrint( | |
2055 precompiledFunctionAst, compiler, | |
2056 monitor: compiler.dumpInfoTask, | |
2057 allowVariableMinification: false).getText()); | |
2058 } | |
2059 | |
2032 outputBuffers[outputUnit] = outputBuffer; | 2060 outputBuffers[outputUnit] = outputBuffer; |
2033 compiler.outputProvider(outputUnit.partFileName(compiler), 'part.js') | 2061 compiler.outputProvider(outputUnit.partFileName(compiler), 'part.js') |
2034 ..add(code) | 2062 ..add(code) |
2035 ..add('${deferredInitializers}["$hash"]$_=$_' | 2063 ..add('${deferredInitializers}["$hash"]$_=$_' |
2036 '${deferredInitializers}.current') | 2064 '${deferredInitializers}.current$N') |
2065 ..add(cspCode.getText()) | |
2037 ..close(); | 2066 ..close(); |
2038 | 2067 |
2039 hunkHashes[outputUnit] = hash; | 2068 hunkHashes[outputUnit] = hash; |
2040 // TODO(johnniwinther): Support source maps for deferred code. | 2069 // TODO(johnniwinther): Support source maps for deferred code. |
2041 } | 2070 } |
2042 return hunkHashes; | 2071 return hunkHashes; |
2043 } | 2072 } |
2044 | 2073 |
2045 String buildGeneratedBy() { | 2074 String buildGeneratedBy() { |
2046 var suffix = ''; | 2075 var suffix = ''; |
(...skipping 26 matching lines...) Expand all Loading... | |
2073 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2102 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
2074 if (element.isInstanceMember) { | 2103 if (element.isInstanceMember) { |
2075 cachedClassBuilders.remove(element.enclosingClass); | 2104 cachedClassBuilders.remove(element.enclosingClass); |
2076 | 2105 |
2077 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2106 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
2078 | 2107 |
2079 } | 2108 } |
2080 } | 2109 } |
2081 } | 2110 } |
2082 } | 2111 } |
OLD | NEW |