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> neededClasses; | |
| 48 Set<ClassElement> instantiatedClasses; | |
|
ngeoffray
2012/12/13 14:52:12
Please add a TODO(ngeoffray): to remove this field
karlklose
2012/12/13 14:56:45
Done.
| |
| 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'"); | |
| 779 for (ClassElement check in typeChecks[cls]) { | |
| 780 buffer.add(',$_${namer.operatorIs(check)}:${_}true'); | |
| 781 }; | |
| 782 buffer.add('}$N'); | |
| 783 } | |
| 784 | |
| 785 // Create representation objects for classes that we do not have a class | |
| 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.${namer.operatorIs(check)}$_=${_}true$N'); | |
| 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 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 void emitClasses(CodeBuffer buffer) { |
| 1181 // Compute the required type checks to know which classes need a | 1226 // Compute the required type checks to know which classes need a |
| 1182 // 'is$' method. | 1227 // 'is$' method. |
| 1183 computeRequiredTypeChecks(); | 1228 computeRequiredTypeChecks(); |
| 1184 | |
| 1185 Set<ClassElement> instantiatedClasses = | |
| 1186 compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter()); | |
| 1187 | |
| 1188 Set<ClassElement> neededClasses = | |
| 1189 new Set<ClassElement>.from(instantiatedClasses); | |
| 1190 | |
| 1191 for (ClassElement element in instantiatedClasses) { | |
| 1192 for (ClassElement superclass = element.superclass; | |
| 1193 superclass != null; | |
| 1194 superclass = superclass.superclass) { | |
| 1195 if (neededClasses.contains(superclass)) break; | |
| 1196 neededClasses.add(superclass); | |
| 1197 } | |
| 1198 } | |
| 1199 List<ClassElement> sortedClasses = | 1229 List<ClassElement> sortedClasses = |
| 1200 new List<ClassElement>.from(neededClasses); | 1230 new List<ClassElement>.from(neededClasses); |
| 1201 sortedClasses.sort((ClassElement class1, ClassElement class2) { | 1231 sortedClasses.sort((ClassElement class1, ClassElement class2) { |
| 1202 // We sort by the ids of the classes. There is no guarantee that these | 1232 // 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 | 1233 // ids are meaningful (or even deterministic), but in the current |
| 1204 // implementation they are increasing within a source file. | 1234 // implementation they are increasing within a source file. |
| 1205 return class1.id - class2.id; | 1235 return class1.id - class2.id; |
| 1206 }); | 1236 }); |
| 1207 | 1237 |
| 1208 // If we need noSuchMethod support, we run through all needed | 1238 // If we need noSuchMethod support, we run through all needed |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1932 for (ClassElement cls in classes) { | 1962 for (ClassElement cls in classes) { |
| 1933 if (compiler.codegenWorld.instantiatedClasses.contains(cls)) { | 1963 if (compiler.codegenWorld.instantiatedClasses.contains(cls)) { |
| 1934 buffer.add('\n$_$_'); | 1964 buffer.add('\n$_$_'); |
| 1935 emitInterceptorCheck(cls, buffer); | 1965 emitInterceptorCheck(cls, buffer); |
| 1936 } | 1966 } |
| 1937 } | 1967 } |
| 1938 buffer.add('\n$_${_}return $objectName.prototype;$n}$N'); | 1968 buffer.add('\n$_${_}return $objectName.prototype;$n}$N'); |
| 1939 }); | 1969 }); |
| 1940 } | 1970 } |
| 1941 | 1971 |
| 1972 void computeNeededClasses() { | |
| 1973 instantiatedClasses = | |
| 1974 compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter()); | |
| 1975 neededClasses = new Set<ClassElement>.from(instantiatedClasses); | |
| 1976 for (ClassElement element in instantiatedClasses) { | |
| 1977 for (ClassElement superclass = element.superclass; | |
| 1978 superclass != null; | |
| 1979 superclass = superclass.superclass) { | |
| 1980 if (neededClasses.contains(superclass)) break; | |
| 1981 neededClasses.add(superclass); | |
| 1982 } | |
| 1983 } | |
| 1984 } | |
| 1985 | |
| 1942 String assembleProgram() { | 1986 String assembleProgram() { |
| 1943 measure(() { | 1987 measure(() { |
| 1988 computeNeededClasses(); | |
| 1989 | |
| 1944 mainBuffer.add(GENERATED_BY); | 1990 mainBuffer.add(GENERATED_BY); |
| 1945 if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE); | 1991 if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE); |
| 1946 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); | 1992 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); |
| 1947 mainBuffer.add('init()$N$n'); | 1993 mainBuffer.add('init()$N$n'); |
| 1948 // Shorten the code by using "$$" as temporary. | 1994 // Shorten the code by using "$$" as temporary. |
| 1949 classesCollector = r"$$"; | 1995 classesCollector = r"$$"; |
| 1950 mainBuffer.add('var $classesCollector$_=$_{}$N'); | 1996 mainBuffer.add('var $classesCollector$_=$_{}$N'); |
| 1951 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. | 1997 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. |
| 1952 isolateProperties = namer.CURRENT_ISOLATE; | 1998 isolateProperties = namer.CURRENT_ISOLATE; |
| 1953 mainBuffer.add( | 1999 mainBuffer.add( |
| 1954 'var $isolateProperties$_=$_$isolatePropertiesName$N'); | 2000 'var $isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1955 emitClasses(mainBuffer); | 2001 emitClasses(mainBuffer); |
| 1956 mainBuffer.add(boundClosureBuffer); | 2002 mainBuffer.add(boundClosureBuffer); |
| 1957 // Clear the buffer, so that we can reuse it for the native classes. | 2003 // Clear the buffer, so that we can reuse it for the native classes. |
| 1958 boundClosureBuffer.clear(); | 2004 boundClosureBuffer.clear(); |
| 1959 emitStaticFunctions(mainBuffer); | 2005 emitStaticFunctions(mainBuffer); |
| 1960 emitStaticFunctionGetters(mainBuffer); | 2006 emitStaticFunctionGetters(mainBuffer); |
| 1961 // We need to finish the classes before we construct compile time | 2007 // We need to finish the classes before we construct compile time |
| 1962 // constants. | 2008 // constants. |
| 1963 emitFinishClassesInvocationIfNecessary(mainBuffer); | 2009 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 2010 emitRuntimeClassesAndTests(mainBuffer); | |
| 1964 emitCompileTimeConstants(mainBuffer); | 2011 emitCompileTimeConstants(mainBuffer); |
| 1965 // Static field initializations require the classes and compile-time | 2012 // Static field initializations require the classes and compile-time |
| 1966 // constants to be set up. | 2013 // constants to be set up. |
| 1967 emitStaticNonFinalFieldInitializations(mainBuffer); | 2014 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 1968 emitGetInterceptorMethods(mainBuffer); | 2015 emitGetInterceptorMethods(mainBuffer); |
| 1969 emitLazilyInitializedStaticFields(mainBuffer); | 2016 emitLazilyInitializedStaticFields(mainBuffer); |
| 1970 | 2017 |
| 1971 isolateProperties = isolatePropertiesName; | 2018 isolateProperties = isolatePropertiesName; |
| 1972 // The following code should not use the short-hand for the | 2019 // The following code should not use the short-hand for the |
| 1973 // initialStatics. | 2020 // initialStatics. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2019 """; | 2066 """; |
| 2020 const String HOOKS_API_USAGE = """ | 2067 const String HOOKS_API_USAGE = """ |
| 2021 // The code supports the following hooks: | 2068 // The code supports the following hooks: |
| 2022 // dartPrint(message) - if this function is defined it is called | 2069 // dartPrint(message) - if this function is defined it is called |
| 2023 // instead of the Dart [print] method. | 2070 // instead of the Dart [print] method. |
| 2024 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2071 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2025 // method will not be invoked directly. | 2072 // method will not be invoked directly. |
| 2026 // Instead, a closure that will invoke [main] is | 2073 // Instead, a closure that will invoke [main] is |
| 2027 // passed to [dartMainRunner]. | 2074 // passed to [dartMainRunner]. |
| 2028 """; | 2075 """; |
| OLD | NEW |