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 String get _ => compiler.enableMinification ? "" : " "; | 50 String get _ => compiler.enableMinification ? "" : " "; |
| 49 String get n => compiler.enableMinification ? "" : "\n"; | 51 String get n => compiler.enableMinification ? "" : "\n"; |
| 50 String get N => compiler.enableMinification ? "\n" : ";\n"; | 52 String get N => compiler.enableMinification ? "\n" : ";\n"; |
| 51 | 53 |
| 52 /** | 54 /** |
| 53 * A cache of closures that are used to closurize instance methods. | 55 * A cache of closures that are used to closurize instance methods. |
| 54 * A closure is dynamically bound to the instance used when | 56 * A closure is dynamically bound to the instance used when |
| 55 * closurized. | 57 * closurized. |
| 56 */ | 58 */ |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 750 // Emit the noSuchMethod handlers on the Object prototype now, | 752 // Emit the noSuchMethod handlers on the Object prototype now, |
| 751 // so that the code in the dynamicFunction helper can find | 753 // so that the code in the dynamicFunction helper can find |
| 752 // them. Note that this helper is invoked before analyzing the | 754 // them. Note that this helper is invoked before analyzing the |
| 753 // full JS script. | 755 // full JS script. |
| 754 if (!nativeEmitter.handleNoSuchMethod) { | 756 if (!nativeEmitter.handleNoSuchMethod) { |
| 755 emitNoSuchMethodHandlers(defineInstanceMember); | 757 emitNoSuchMethodHandlers(defineInstanceMember); |
| 756 } | 758 } |
| 757 } | 759 } |
| 758 } | 760 } |
| 759 | 761 |
| 762 void emitRuntimeClassesAndTests(CodeBuffer buffer) { | |
| 763 JavaScriptBackend backend = compiler.backend; | |
| 764 RuntimeTypeInformation rti = backend.rti; | |
| 765 | |
| 766 TypeChecks typeChecks = rti.computeRequiredChecks(); | |
| 767 | |
| 768 bool needsHolder(ClassElement cls) { | |
| 769 return !neededClasses.contains(cls) || cls.isNative() || | |
| 770 rti.isJsNative(cls); | |
| 771 } | |
| 772 | |
| 773 void maybeGenerateHolder(ClassElement cls) { | |
| 774 if (!needsHolder(cls)) return; | |
| 775 | |
| 776 String holder = namer.isolateAccess(cls); | |
| 777 String name = namer.getName(cls); | |
| 778 buffer.add("$holder$_=$_{builtin\$cls:$_'$name'"); | |
|
ngeoffray
2012/12/13 13:34:58
I think you can share the following code with the
karlklose
2012/12/13 14:37:34
I want to generate the checks for the synthetic ho
| |
| 779 for (ClassElement check in typeChecks[cls]) { | |
| 780 buffer.add(',${_}is\$${namer.getName(check)}:${_}true'); | |
|
ngeoffray
2012/12/13 13:34:58
Please use namer.operatorIs.
karlklose
2012/12/13 14:37:34
Done.
| |
| 781 }; | |
| 782 buffer.add('}$N'); | |
| 783 } | |
| 784 | |
| 785 // Create representation objects for classes that we do not need a class | |
|
ngeoffray
2012/12/13 13:34:58
do not need -> do not have
karlklose
2012/12/13 14:37:34
Done.
| |
| 786 // definition for (because they are uninstantiated or native). | |
| 787 for (ClassElement cls in rti.allArguments) { | |
| 788 maybeGenerateHolder(cls); | |
| 789 } | |
| 790 | |
| 791 // Add checks to the constructors of instantiated classes. | |
| 792 for (ClassElement cls in typeChecks) { | |
| 793 if (needsHolder(cls)) { | |
| 794 // We already emitted the is-checks in the object definition for this | |
| 795 // class. | |
| 796 continue; | |
| 797 } | |
| 798 String holder = namer.isolateAccess(cls); | |
| 799 for (ClassElement check in typeChecks[cls]) { | |
| 800 buffer.add('$holder.is\$${namer.getName(check)} = true;\n'); | |
|
ngeoffray
2012/12/13 13:34:58
namer.operatorIs.
karlklose
2012/12/13 14:37:34
Done.
| |
| 801 }; | |
| 802 } | |
| 803 } | |
| 804 | |
| 760 /** | 805 /** |
| 761 * Documentation wanted -- johnniwinther | 806 * Documentation wanted -- johnniwinther |
| 762 * | 807 * |
| 763 * Invariant: [classElement] must be a declaration element. | 808 * Invariant: [classElement] must be a declaration element. |
| 764 */ | 809 */ |
| 765 void visitClassFields(ClassElement classElement, | 810 void visitClassFields(ClassElement classElement, |
| 766 void addField(Element member, | 811 void addField(Element member, |
| 767 String name, | 812 String name, |
| 768 String accessorName, | 813 String accessorName, |
| 769 bool needsGetter, | 814 bool needsGetter, |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1170 // Add unneeded interceptors to the [unneededClasses] set. | 1215 // Add unneeded interceptors to the [unneededClasses] set. |
| 1171 for (ClassElement interceptor in backend.interceptedClasses.keys) { | 1216 for (ClassElement interceptor in backend.interceptedClasses.keys) { |
| 1172 if (!needed.contains(interceptor)) { | 1217 if (!needed.contains(interceptor)) { |
| 1173 unneededClasses.add(interceptor); | 1218 unneededClasses.add(interceptor); |
| 1174 } | 1219 } |
| 1175 } | 1220 } |
| 1176 | 1221 |
| 1177 return (ClassElement cls) => !unneededClasses.contains(cls); | 1222 return (ClassElement cls) => !unneededClasses.contains(cls); |
| 1178 } | 1223 } |
| 1179 | 1224 |
| 1180 void emitClasses(CodeBuffer buffer) { | 1225 Set<ClassElement> get instantiatedClasses { |
|
ngeoffray
2012/12/13 13:34:58
Do you need this? If it's only used by the neededC
karlklose
2012/12/13 14:37:34
It is also needed in emitClasses.
| |
| 1181 // Compute the required type checks to know which classes need a | 1226 if (cachedInstantiatedClasses != null) return cachedInstantiatedClasses; |
| 1182 // 'is$' method. | 1227 cachedInstantiatedClasses = |
| 1183 computeRequiredTypeChecks(); | 1228 compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter()); |
| 1229 return cachedInstantiatedClasses; | |
| 1230 } | |
| 1184 | 1231 |
| 1185 Set<ClassElement> instantiatedClasses = | 1232 /// Get or compute the classes that we need to emit. |
| 1186 compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter()); | 1233 Set<ClassElement> get neededClasses { |
|
ngeoffray
2012/12/13 13:34:58
Instead of doing this lazily I would definitely pr
karlklose
2012/12/13 14:37:34
Done.
| |
| 1234 if (cachedNeededClasses != null) return cachedNeededClasses; | |
| 1187 | 1235 |
| 1188 Set<ClassElement> neededClasses = | 1236 cachedNeededClasses = new Set<ClassElement>.from(instantiatedClasses); |
| 1189 new Set<ClassElement>.from(instantiatedClasses); | |
| 1190 | 1237 |
| 1191 for (ClassElement element in instantiatedClasses) { | 1238 for (ClassElement element in instantiatedClasses) { |
| 1192 for (ClassElement superclass = element.superclass; | 1239 for (ClassElement superclass = element.superclass; |
| 1193 superclass != null; | 1240 superclass != null; |
| 1194 superclass = superclass.superclass) { | 1241 superclass = superclass.superclass) { |
| 1195 if (neededClasses.contains(superclass)) break; | 1242 if (neededClasses.contains(superclass)) break; |
| 1196 neededClasses.add(superclass); | 1243 neededClasses.add(superclass); |
| 1197 } | 1244 } |
| 1198 } | 1245 } |
| 1246 | |
| 1247 return cachedNeededClasses; | |
| 1248 } | |
| 1249 | |
| 1250 void emitClasses(CodeBuffer buffer) { | |
| 1251 // Compute the required type checks to know which classes need a | |
| 1252 // 'is$' method. | |
| 1253 computeRequiredTypeChecks(); | |
| 1199 List<ClassElement> sortedClasses = | 1254 List<ClassElement> sortedClasses = |
| 1200 new List<ClassElement>.from(neededClasses); | 1255 new List<ClassElement>.from(neededClasses); |
| 1201 sortedClasses.sort((ClassElement class1, ClassElement class2) { | 1256 sortedClasses.sort((ClassElement class1, ClassElement class2) { |
| 1202 // We sort by the ids of the classes. There is no guarantee that these | 1257 // We sort by the ids of the classes. There is no guarantee that these |
| 1203 // ids are meaningful (or even deterministic), but in the current | 1258 // ids are meaningful (or even deterministic), but in the current |
| 1204 // implementation they are increasing within a source file. | 1259 // implementation they are increasing within a source file. |
| 1205 return class1.id - class2.id; | 1260 return class1.id - class2.id; |
| 1206 }); | 1261 }); |
| 1207 | 1262 |
| 1208 // If we need noSuchMethod support, we run through all needed | 1263 // If we need noSuchMethod support, we run through all needed |
| (...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1954 'var $isolateProperties$_=$_$isolatePropertiesName$N'); | 2009 'var $isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1955 emitClasses(mainBuffer); | 2010 emitClasses(mainBuffer); |
| 1956 mainBuffer.add(boundClosureBuffer); | 2011 mainBuffer.add(boundClosureBuffer); |
| 1957 // Clear the buffer, so that we can reuse it for the native classes. | 2012 // Clear the buffer, so that we can reuse it for the native classes. |
| 1958 boundClosureBuffer.clear(); | 2013 boundClosureBuffer.clear(); |
| 1959 emitStaticFunctions(mainBuffer); | 2014 emitStaticFunctions(mainBuffer); |
| 1960 emitStaticFunctionGetters(mainBuffer); | 2015 emitStaticFunctionGetters(mainBuffer); |
| 1961 // We need to finish the classes before we construct compile time | 2016 // We need to finish the classes before we construct compile time |
| 1962 // constants. | 2017 // constants. |
| 1963 emitFinishClassesInvocationIfNecessary(mainBuffer); | 2018 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 2019 emitRuntimeClassesAndTests(mainBuffer); | |
| 1964 emitCompileTimeConstants(mainBuffer); | 2020 emitCompileTimeConstants(mainBuffer); |
| 1965 // Static field initializations require the classes and compile-time | 2021 // Static field initializations require the classes and compile-time |
| 1966 // constants to be set up. | 2022 // constants to be set up. |
| 1967 emitStaticNonFinalFieldInitializations(mainBuffer); | 2023 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 1968 emitGetInterceptorMethods(mainBuffer); | 2024 emitGetInterceptorMethods(mainBuffer); |
| 1969 emitLazilyInitializedStaticFields(mainBuffer); | 2025 emitLazilyInitializedStaticFields(mainBuffer); |
| 1970 | 2026 |
| 1971 isolateProperties = isolatePropertiesName; | 2027 isolateProperties = isolatePropertiesName; |
| 1972 // The following code should not use the short-hand for the | 2028 // The following code should not use the short-hand for the |
| 1973 // initialStatics. | 2029 // initialStatics. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2019 """; | 2075 """; |
| 2020 const String HOOKS_API_USAGE = """ | 2076 const String HOOKS_API_USAGE = """ |
| 2021 // The code supports the following hooks: | 2077 // The code supports the following hooks: |
| 2022 // dartPrint(message) - if this function is defined it is called | 2078 // dartPrint(message) - if this function is defined it is called |
| 2023 // instead of the Dart [print] method. | 2079 // instead of the Dart [print] method. |
| 2024 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2080 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2025 // method will not be invoked directly. | 2081 // method will not be invoked directly. |
| 2026 // Instead, a closure that will invoke [main] is | 2082 // Instead, a closure that will invoke [main] is |
| 2027 // passed to [dartMainRunner]. | 2083 // passed to [dartMainRunner]. |
| 2028 """; | 2084 """; |
| OLD | NEW |