OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 | 7 |
8 class OldEmitter implements Emitter { | 8 class OldEmitter implements Emitter { |
9 final Compiler compiler; | 9 final Compiler compiler; |
10 final CodeEmitterTask task; | 10 final CodeEmitterTask task; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 String get generateAccessorHolder | 152 String get generateAccessorHolder |
153 => '$isolatePropertiesName.\$generateAccessor'; | 153 => '$isolatePropertiesName.\$generateAccessor'; |
154 String get finishClassesProperty | 154 String get finishClassesProperty |
155 => r'$finishClasses'; | 155 => r'$finishClasses'; |
156 String get finishClassesName | 156 String get finishClassesName |
157 => '${namer.isolateName}.$finishClassesProperty'; | 157 => '${namer.isolateName}.$finishClassesProperty'; |
158 String get finishIsolateConstructorName | 158 String get finishIsolateConstructorName |
159 => '${namer.isolateName}.\$finishIsolateConstructor'; | 159 => '${namer.isolateName}.\$finishIsolateConstructor'; |
160 String get isolatePropertiesName | 160 String get isolatePropertiesName |
161 => '${namer.isolateName}.${namer.isolatePropertiesName}'; | 161 => '${namer.isolateName}.${namer.isolatePropertiesName}'; |
| 162 String get lazyInitializerProperty |
| 163 => r'$lazy'; |
162 String get lazyInitializerName | 164 String get lazyInitializerName |
163 => '${namer.isolateName}.\$lazy'; | 165 => '${namer.isolateName}.${lazyInitializerProperty}'; |
164 String get initName => 'init'; | 166 String get initName => 'init'; |
165 String get makeConstListProperty | 167 String get makeConstListProperty |
166 => namer.getMappedInstanceName('makeConstantList'); | 168 => namer.getMappedInstanceName('makeConstantList'); |
167 | 169 |
168 /// The name of the property that contains all field names. | 170 /// The name of the property that contains all field names. |
169 /// | 171 /// |
170 /// This property is added to constructors when isolate support is enabled. | 172 /// This property is added to constructors when isolate support is enabled. |
171 static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__"; | 173 static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__"; |
172 | 174 |
173 /// For deferred loading we communicate the initializers via this global var. | 175 /// For deferred loading we communicate the initializers via this global var. |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 'leafTagsAccess': leafTagsAccess, | 683 'leafTagsAccess': leafTagsAccess, |
682 'allowNativesSubclassing': true}); | 684 'allowNativesSubclassing': true}); |
683 } | 685 } |
684 | 686 |
685 jsAst.Fun get finishIsolateConstructorFunction { | 687 jsAst.Fun get finishIsolateConstructorFunction { |
686 // We replace the old Isolate function with a new one that initializes | 688 // We replace the old Isolate function with a new one that initializes |
687 // all its fields with the initial (and often final) value of all globals. | 689 // all its fields with the initial (and often final) value of all globals. |
688 // | 690 // |
689 // We also copy over old values like the prototype, and the | 691 // We also copy over old values like the prototype, and the |
690 // isolateProperties themselves. | 692 // isolateProperties themselves. |
691 return js(''' | 693 return js( |
| 694 """ |
692 function (oldIsolate) { | 695 function (oldIsolate) { |
693 var isolateProperties = oldIsolate.#; // isolatePropertiesName | 696 var isolateProperties = oldIsolate.#isolatePropertiesName; |
694 function Isolate() { | 697 function Isolate() { |
695 var hasOwnProperty = Object.prototype.hasOwnProperty; | 698 var hasOwnProperty = Object.prototype.hasOwnProperty; |
696 for (var staticName in isolateProperties) | 699 for (var staticName in isolateProperties) |
697 if (hasOwnProperty.call(isolateProperties, staticName)) | 700 if (hasOwnProperty.call(isolateProperties, staticName)) |
698 this[staticName] = isolateProperties[staticName]; | 701 this[staticName] = isolateProperties[staticName]; |
699 | 702 |
700 // Reset lazy initializers to null. | 703 // Reset lazy initializers to null. |
701 // When forcing the object to fast mode (below) v8 will consider | 704 // When forcing the object to fast mode (below) v8 will consider |
702 // functions as part the object's map. Since we will change them | 705 // functions as part the object's map. Since we will change them |
703 // (after the first call to the getter), we would have a map | 706 // (after the first call to the getter), we would have a map |
(...skipping 11 matching lines...) Expand all Loading... |
715 new ForceEfficientMap(); | 718 new ForceEfficientMap(); |
716 | 719 |
717 // Now, after being a fast map we can set the lazies again. | 720 // Now, after being a fast map we can set the lazies again. |
718 for (var lazyInit in lazies) { | 721 for (var lazyInit in lazies) { |
719 var lazyInitName = lazies[lazyInit]; | 722 var lazyInitName = lazies[lazyInit]; |
720 this[lazyInitName] = isolateProperties[lazyInitName]; | 723 this[lazyInitName] = isolateProperties[lazyInitName]; |
721 } | 724 } |
722 } | 725 } |
723 Isolate.prototype = oldIsolate.prototype; | 726 Isolate.prototype = oldIsolate.prototype; |
724 Isolate.prototype.constructor = Isolate; | 727 Isolate.prototype.constructor = Isolate; |
725 Isolate.# = isolateProperties; // isolatePropertiesName | 728 Isolate.#isolatePropertiesName = isolateProperties; |
726 if (#) // needsDefineClass. | 729 if (#needsDefineClass) |
727 Isolate.# = oldIsolate.#; // finishClassesProperty * 2 | 730 Isolate.#finishClassesProperty = oldIsolate.#finishClassesProperty; |
728 if (#) // outputContainsConstantList | 731 if (#outputContainsConstantList) |
729 Isolate.# = oldIsolate.#; // makeConstListProperty * 2 | 732 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; |
730 return Isolate; | 733 if (#hasIncrementalSupport) |
731 }''', | 734 Isolate.#lazyInitializerProperty = |
732 [namer.isolatePropertiesName, namer.isolatePropertiesName, | 735 oldIsolate.#lazyInitializerProperty; |
733 needsDefineClass, finishClassesProperty, finishClassesProperty, | 736 return Isolate; |
734 task.outputContainsConstantList, | 737 } |
735 makeConstListProperty, makeConstListProperty ]); | 738 """, |
| 739 { 'isolatePropertiesName': namer.isolatePropertiesName, |
| 740 'needsDefineClass': needsDefineClass, |
| 741 'finishClassesProperty': finishClassesProperty, |
| 742 'outputContainsConstantList': task.outputContainsConstantList, |
| 743 'makeConstListProperty': makeConstListProperty, |
| 744 'hasIncrementalSupport': compiler.hasIncrementalSupport, |
| 745 'lazyInitializerProperty': lazyInitializerProperty, |
| 746 }); |
736 } | 747 } |
737 | 748 |
738 jsAst.Fun get lazyInitializerFunction { | 749 jsAst.Fun get lazyInitializerFunction { |
739 String isolate = namer.currentIsolate; | 750 String isolate = namer.currentIsolate; |
740 jsAst.Expression cyclicThrow = | 751 jsAst.Expression cyclicThrow = |
741 staticFunctionAccess(backend.getCyclicThrowHelper()); | 752 staticFunctionAccess(backend.getCyclicThrowHelper()); |
742 jsAst.Expression laziesAccess = | 753 jsAst.Expression laziesAccess = |
743 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); | 754 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); |
744 | 755 |
745 return js(''' | 756 return js(''' |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 } | 1027 } |
1017 } | 1028 } |
1018 | 1029 |
1019 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { | 1030 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { |
1020 JavaScriptConstantCompiler handler = backend.constants; | 1031 JavaScriptConstantCompiler handler = backend.constants; |
1021 List<VariableElement> lazyFields = | 1032 List<VariableElement> lazyFields = |
1022 handler.getLazilyInitializedFieldsForEmission(); | 1033 handler.getLazilyInitializedFieldsForEmission(); |
1023 if (!lazyFields.isEmpty) { | 1034 if (!lazyFields.isEmpty) { |
1024 needsLazyInitializer = true; | 1035 needsLazyInitializer = true; |
1025 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { | 1036 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { |
1026 jsAst.Expression code = backend.generatedCode[element]; | 1037 jsAst.Expression init = |
1027 // The code is null if we ended up not needing the lazily | 1038 buildLazilyInitializedStaticField(element, isolateProperties); |
1028 // initialized field after all because of constant folding | 1039 if (init == null) continue; |
1029 // before code generation. | 1040 buffer.write( |
1030 if (code == null) continue; | 1041 jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask)); |
1031 // The code only computes the initial value. We build the lazy-check | |
1032 // here: | |
1033 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); | |
1034 // The name is used for error reporting. The 'initial' must be a | |
1035 // closure that constructs the initial value. | |
1036 jsAst.Expression init = js('#(#,#,#,#,#)', | |
1037 [js(lazyInitializerName), | |
1038 js(isolateProperties), | |
1039 js.string(element.name), | |
1040 js.string(namer.getNameX(element)), | |
1041 js.string(namer.getLazyInitializerName(element)), | |
1042 code]); | |
1043 buffer.write(jsAst.prettyPrint(init, compiler, | |
1044 monitor: compiler.dumpInfoTask)); | |
1045 buffer.write("$N"); | 1042 buffer.write("$N"); |
1046 } | 1043 } |
1047 } | 1044 } |
1048 } | 1045 } |
1049 | 1046 |
| 1047 jsAst.Expression buildLazilyInitializedStaticField( |
| 1048 VariableElement element, String isolateProperties) { |
| 1049 jsAst.Expression code = backend.generatedCode[element]; |
| 1050 // The code is null if we ended up not needing the lazily |
| 1051 // initialized field after all because of constant folding |
| 1052 // before code generation. |
| 1053 if (code == null) return null; |
| 1054 // The code only computes the initial value. We build the lazy-check |
| 1055 // here: |
| 1056 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); |
| 1057 // The name is used for error reporting. The 'initial' must be a |
| 1058 // closure that constructs the initial value. |
| 1059 return js('#(#,#,#,#,#)', |
| 1060 [js(lazyInitializerName), |
| 1061 js(isolateProperties), |
| 1062 js.string(element.name), |
| 1063 js.string(namer.getNameX(element)), |
| 1064 js.string(namer.getLazyInitializerName(element)), |
| 1065 code]); |
| 1066 } |
| 1067 |
1050 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { | 1068 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
1051 if (constant.isFunction) return true; // Already emitted. | 1069 if (constant.isFunction) return true; // Already emitted. |
1052 if (constant.isPrimitive) return true; // Inlined. | 1070 if (constant.isPrimitive) return true; // Inlined. |
1053 if (constant.isDummy) return true; // Inlined. | 1071 if (constant.isDummy) return true; // Inlined. |
1054 // The name is null when the constant is already a JS constant. | 1072 // The name is null when the constant is already a JS constant. |
1055 // TODO(floitsch): every constant should be registered, so that we can | 1073 // TODO(floitsch): every constant should be registered, so that we can |
1056 // share the ones that take up too much space (like some strings). | 1074 // share the ones that take up too much space (like some strings). |
1057 if (namer.constantName(constant) == null) return true; | 1075 if (namer.constantName(constant) == null) return true; |
1058 return false; | 1076 return false; |
1059 } | 1077 } |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1591 .write('${globalsHolder}.${namer.isolateName}$_=$_' | 1609 .write('${globalsHolder}.${namer.isolateName}$_=$_' |
1592 '${namer.isolateName}$N' | 1610 '${namer.isolateName}$N' |
1593 '${globalsHolder}.$initName$_=${_}$initName$N'); | 1611 '${globalsHolder}.$initName$_=${_}$initName$N'); |
1594 } | 1612 } |
1595 mainBuffer.add('init()$N$n'); | 1613 mainBuffer.add('init()$N$n'); |
1596 mainBuffer.add('$isolateProperties$_=$_$isolatePropertiesName$N'); | 1614 mainBuffer.add('$isolateProperties$_=$_$isolatePropertiesName$N'); |
1597 | 1615 |
1598 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); | 1616 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); |
1599 | 1617 |
1600 // Only output the classesCollector if we actually have any classes. | 1618 // Only output the classesCollector if we actually have any classes. |
1601 if (!(nativeClasses.isEmpty && | 1619 if (needsDefineClass || |
| 1620 !(nativeClasses.isEmpty && |
1602 compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && | 1621 compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && |
1603 outputClassLists.values.every((classList) => classList.isEmpty) && | 1622 outputClassLists.values.every((classList) => classList.isEmpty) && |
1604 typedefsNeededForReflection.isEmpty)) { | 1623 typedefsNeededForReflection.isEmpty)) { |
1605 // Shorten the code by using "$$" as temporary. | 1624 // Shorten the code by using "$$" as temporary. |
1606 classesCollector = r"$$"; | 1625 classesCollector = r"$$"; |
1607 mainBuffer.add('var $classesCollector$_=${_}Object.create(null)$N$n'); | 1626 mainBuffer.add('var $classesCollector$_=${_}Object.create(null)$N$n'); |
1608 } | 1627 } |
1609 | 1628 |
1610 if (!nativeClasses.isEmpty) { | 1629 if (!nativeClasses.isEmpty) { |
1611 addComment('Native classes', mainBuffer); | 1630 addComment('Native classes', mainBuffer); |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2197 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2216 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
2198 if (element.isInstanceMember) { | 2217 if (element.isInstanceMember) { |
2199 cachedClassBuilders.remove(element.enclosingClass); | 2218 cachedClassBuilders.remove(element.enclosingClass); |
2200 | 2219 |
2201 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2220 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
2202 | 2221 |
2203 } | 2222 } |
2204 } | 2223 } |
2205 } | 2224 } |
2206 } | 2225 } |
OLD | NEW |