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 26 matching lines...) Expand all Loading... | |
| 37 bool needsLazyInitializer = false; | 37 bool needsLazyInitializer = false; |
| 38 final Namer namer; | 38 final Namer namer; |
| 39 ConstantEmitter constantEmitter; | 39 ConstantEmitter constantEmitter; |
| 40 NativeEmitter nativeEmitter; | 40 NativeEmitter nativeEmitter; |
| 41 CodeBuffer boundClosureBuffer; | 41 CodeBuffer boundClosureBuffer; |
| 42 CodeBuffer mainBuffer; | 42 CodeBuffer mainBuffer; |
| 43 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 43 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
| 44 well as in the generated code. */ | 44 well as in the generated code. */ |
| 45 String isolateProperties; | 45 String isolateProperties; |
| 46 String classesCollector; | 46 String classesCollector; |
| 47 Set<ClassElement> cachedNeededClasses; | |
| 48 Set<ClassElement> cachedInstantiatedClasses; | |
| 47 | 49 |
| 48 /** | 50 /** |
| 49 * A cache of closures that are used to closurize instance methods. | 51 * A cache of closures that are used to closurize instance methods. |
| 50 * A closure is dynamically bound to the instance used when | 52 * A closure is dynamically bound to the instance used when |
| 51 * closurized. | 53 * closurized. |
| 52 */ | 54 */ |
| 53 final Map<int, String> boundClosureCache; | 55 final Map<int, String> boundClosureCache; |
| 54 | 56 |
| 55 /** | 57 /** |
| 56 * A cache of closures that are used to closurize instance methods | 58 * A cache of closures that are used to closurize instance methods |
| (...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 746 // Emit the noSuchMethod handlers on the Object prototype now, | 748 // Emit the noSuchMethod handlers on the Object prototype now, |
| 747 // so that the code in the dynamicFunction helper can find | 749 // so that the code in the dynamicFunction helper can find |
| 748 // them. Note that this helper is invoked before analyzing the | 750 // them. Note that this helper is invoked before analyzing the |
| 749 // full JS script. | 751 // full JS script. |
| 750 if (!nativeEmitter.handleNoSuchMethod) { | 752 if (!nativeEmitter.handleNoSuchMethod) { |
| 751 emitNoSuchMethodHandlers(defineInstanceMember); | 753 emitNoSuchMethodHandlers(defineInstanceMember); |
| 752 } | 754 } |
| 753 } | 755 } |
| 754 } | 756 } |
| 755 | 757 |
| 758 void emitRuntimeClassesAndTests(CodeBuffer buffer) { | |
| 759 JavaScriptBackend backend = compiler.backend; | |
| 760 RuntimeTypeInformation rti = backend.rti; | |
| 761 | |
| 762 TypeChecks typeChecks = rti.computeRequiredChecks(); | |
| 763 | |
| 764 bool needsHolder(ClassElement cls) { | |
| 765 return !neededClasses.contains(cls) || cls.isNative() || | |
| 766 rti.isJsNative(cls); | |
| 767 } | |
| 768 | |
| 769 void maybeGenerateHolder(ClassElement cls) { | |
| 770 if (!needsHolder(cls)) return; | |
| 771 | |
| 772 String holder = namer.isolateAccess(cls); | |
| 773 String name = namer.getName(cls); | |
| 774 buffer.add("$holder = {builtin\$cls: '$name'"); | |
|
kasperl
2012/12/13 09:48:55
You should be able to use Erik's new whitespace sa
karlklose
2012/12/13 12:55:46
Done.
| |
| 775 for (ClassElement check in typeChecks[cls]) { | |
| 776 buffer.add(', is\$${namer.getName(check)}: true'); | |
| 777 }; | |
| 778 buffer.add('};\n'); | |
| 779 } | |
| 780 | |
| 781 // Create representation objects for classes that we do not need a class | |
| 782 // definition for (because they are uninstantiated or native). | |
| 783 for (ClassElement cls in rti.allArguments) { | |
| 784 maybeGenerateHolder(cls); | |
| 785 } | |
| 786 | |
| 787 // Add checks to the constructors of instantiated classes. | |
| 788 for (ClassElement cls in typeChecks) { | |
| 789 if (needsHolder(cls)) { | |
| 790 // We already emitted the is-checks in the object definition for this | |
| 791 // class. | |
| 792 continue; | |
| 793 } | |
| 794 String holder = namer.isolateAccess(cls); | |
| 795 for (ClassElement check in typeChecks[cls]) { | |
| 796 buffer.add('$holder.is\$${namer.getName(check)} = true;\n'); | |
| 797 }; | |
| 798 } | |
| 799 } | |
| 800 | |
| 756 /** | 801 /** |
| 757 * Documentation wanted -- johnniwinther | 802 * Documentation wanted -- johnniwinther |
| 758 * | 803 * |
| 759 * Invariant: [classElement] must be a declaration element. | 804 * Invariant: [classElement] must be a declaration element. |
| 760 */ | 805 */ |
| 761 void visitClassFields(ClassElement classElement, | 806 void visitClassFields(ClassElement classElement, |
| 762 void addField(Element member, | 807 void addField(Element member, |
| 763 String name, | 808 String name, |
| 764 String accessorName, | 809 String accessorName, |
| 765 bool needsGetter, | 810 bool needsGetter, |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1139 // Add unneeded interceptors to the [unneededClasses] set. | 1184 // Add unneeded interceptors to the [unneededClasses] set. |
| 1140 for (ClassElement interceptor in backend.interceptedClasses.keys) { | 1185 for (ClassElement interceptor in backend.interceptedClasses.keys) { |
| 1141 if (!needed.contains(interceptor)) { | 1186 if (!needed.contains(interceptor)) { |
| 1142 unneededClasses.add(interceptor); | 1187 unneededClasses.add(interceptor); |
| 1143 } | 1188 } |
| 1144 } | 1189 } |
| 1145 | 1190 |
| 1146 return (ClassElement cls) => !unneededClasses.contains(cls); | 1191 return (ClassElement cls) => !unneededClasses.contains(cls); |
| 1147 } | 1192 } |
| 1148 | 1193 |
| 1149 void emitClasses(CodeBuffer buffer) { | 1194 Set<ClassElement> get instantiatedClasses { |
| 1150 // Compute the required type checks to know which classes need a | 1195 if (cachedInstantiatedClasses != null) return cachedInstantiatedClasses; |
| 1151 // 'is$' method. | 1196 cachedInstantiatedClasses = |
| 1152 computeRequiredTypeChecks(); | 1197 compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter()); |
| 1198 return cachedInstantiatedClasses; | |
| 1199 } | |
| 1153 | 1200 |
| 1154 Set<ClassElement> instantiatedClasses = | 1201 /// Get or Compute the classes that we need to emit. |
|
kasperl
2012/12/13 09:48:55
Compute -> compute
karlklose
2012/12/13 12:55:46
Done.
| |
| 1155 compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter()); | 1202 Set<ClassElement> get neededClasses { |
| 1203 if (cachedNeededClasses != null) return cachedNeededClasses; | |
| 1156 | 1204 |
| 1157 Set<ClassElement> neededClasses = | 1205 cachedNeededClasses = new Set<ClassElement>.from(instantiatedClasses); |
| 1158 new Set<ClassElement>.from(instantiatedClasses); | |
| 1159 | 1206 |
| 1160 for (ClassElement element in instantiatedClasses) { | 1207 for (ClassElement element in instantiatedClasses) { |
| 1161 for (ClassElement superclass = element.superclass; | 1208 for (ClassElement superclass = element.superclass; |
| 1162 superclass != null; | 1209 superclass != null; |
| 1163 superclass = superclass.superclass) { | 1210 superclass = superclass.superclass) { |
| 1164 if (neededClasses.contains(superclass)) break; | 1211 if (neededClasses.contains(superclass)) break; |
| 1165 neededClasses.add(superclass); | 1212 neededClasses.add(superclass); |
| 1166 } | 1213 } |
| 1167 } | 1214 } |
| 1215 | |
| 1216 return cachedNeededClasses; | |
| 1217 } | |
| 1218 | |
| 1219 void emitClasses(CodeBuffer buffer) { | |
| 1220 // Compute the required type checks to know which classes need a | |
| 1221 // 'is$' method. | |
| 1222 computeRequiredTypeChecks(); | |
| 1168 List<ClassElement> sortedClasses = | 1223 List<ClassElement> sortedClasses = |
| 1169 new List<ClassElement>.from(neededClasses); | 1224 new List<ClassElement>.from(neededClasses); |
| 1170 sortedClasses.sort((ClassElement class1, ClassElement class2) { | 1225 sortedClasses.sort((ClassElement class1, ClassElement class2) { |
| 1171 // We sort by the ids of the classes. There is no guarantee that these | 1226 // We sort by the ids of the classes. There is no guarantee that these |
| 1172 // ids are meaningful (or even deterministic), but in the current | 1227 // ids are meaningful (or even deterministic), but in the current |
| 1173 // implementation they are increasing within a source file. | 1228 // implementation they are increasing within a source file. |
| 1174 return class1.id - class2.id; | 1229 return class1.id - class2.id; |
| 1175 }); | 1230 }); |
| 1176 | 1231 |
| 1177 // If we need noSuchMethod support, we run through all needed | 1232 // If we need noSuchMethod support, we run through all needed |
| (...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1911 mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n'); | 1966 mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n'); |
| 1912 emitClasses(mainBuffer); | 1967 emitClasses(mainBuffer); |
| 1913 mainBuffer.add(boundClosureBuffer); | 1968 mainBuffer.add(boundClosureBuffer); |
| 1914 // Clear the buffer, so that we can reuse it for the native classes. | 1969 // Clear the buffer, so that we can reuse it for the native classes. |
| 1915 boundClosureBuffer.clear(); | 1970 boundClosureBuffer.clear(); |
| 1916 emitStaticFunctions(mainBuffer); | 1971 emitStaticFunctions(mainBuffer); |
| 1917 emitStaticFunctionGetters(mainBuffer); | 1972 emitStaticFunctionGetters(mainBuffer); |
| 1918 // We need to finish the classes before we construct compile time | 1973 // We need to finish the classes before we construct compile time |
| 1919 // constants. | 1974 // constants. |
| 1920 emitFinishClassesInvocationIfNecessary(mainBuffer); | 1975 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1976 emitRuntimeClassesAndTests(mainBuffer); | |
| 1921 emitCompileTimeConstants(mainBuffer); | 1977 emitCompileTimeConstants(mainBuffer); |
| 1922 // Static field initializations require the classes and compile-time | 1978 // Static field initializations require the classes and compile-time |
| 1923 // constants to be set up. | 1979 // constants to be set up. |
| 1924 emitStaticNonFinalFieldInitializations(mainBuffer); | 1980 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 1925 emitGetInterceptorMethods(mainBuffer); | 1981 emitGetInterceptorMethods(mainBuffer); |
| 1926 emitLazilyInitializedStaticFields(mainBuffer); | 1982 emitLazilyInitializedStaticFields(mainBuffer); |
| 1927 | 1983 |
| 1928 isolateProperties = isolatePropertiesName; | 1984 isolateProperties = isolatePropertiesName; |
| 1929 // The following code should not use the short-hand for the | 1985 // The following code should not use the short-hand for the |
| 1930 // initialStatics. | 1986 // initialStatics. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1974 const String HOOKS_API_USAGE = """ | 2030 const String HOOKS_API_USAGE = """ |
| 1975 // Generated by dart2js, the Dart to JavaScript compiler. | 2031 // Generated by dart2js, the Dart to JavaScript compiler. |
| 1976 // The code supports the following hooks: | 2032 // The code supports the following hooks: |
| 1977 // dartPrint(message) - if this function is defined it is called | 2033 // dartPrint(message) - if this function is defined it is called |
| 1978 // instead of the Dart [print] method. | 2034 // instead of the Dart [print] method. |
| 1979 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2035 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 1980 // method will not be invoked directly. | 2036 // method will not be invoked directly. |
| 1981 // Instead, a closure that will invoke [main] is | 2037 // Instead, a closure that will invoke [main] is |
| 1982 // passed to [dartMainRunner]. | 2038 // passed to [dartMainRunner]. |
| 1983 """; | 2039 """; |
| OLD | NEW |