| 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 // TODO(ngeoffray): remove this field. |
| 49 Set<ClassElement> instantiatedClasses; |
| 47 | 50 |
| 48 String get _ => compiler.enableMinification ? "" : " "; | 51 String get _ => compiler.enableMinification ? "" : " "; |
| 49 String get n => compiler.enableMinification ? "" : "\n"; | 52 String get n => compiler.enableMinification ? "" : "\n"; |
| 50 String get N => compiler.enableMinification ? "\n" : ";\n"; | 53 String get N => compiler.enableMinification ? "\n" : ";\n"; |
| 51 | 54 |
| 52 /** | 55 /** |
| 53 * A cache of closures that are used to closurize instance methods. | 56 * A cache of closures that are used to closurize instance methods. |
| 54 * A closure is dynamically bound to the instance used when | 57 * A closure is dynamically bound to the instance used when |
| 55 * closurized. | 58 * closurized. |
| 56 */ | 59 */ |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 // Emit the noSuchMethod handlers on the Object prototype now, | 753 // Emit the noSuchMethod handlers on the Object prototype now, |
| 751 // so that the code in the dynamicFunction helper can find | 754 // so that the code in the dynamicFunction helper can find |
| 752 // them. Note that this helper is invoked before analyzing the | 755 // them. Note that this helper is invoked before analyzing the |
| 753 // full JS script. | 756 // full JS script. |
| 754 if (!nativeEmitter.handleNoSuchMethod) { | 757 if (!nativeEmitter.handleNoSuchMethod) { |
| 755 emitNoSuchMethodHandlers(defineInstanceMember); | 758 emitNoSuchMethodHandlers(defineInstanceMember); |
| 756 } | 759 } |
| 757 } | 760 } |
| 758 } | 761 } |
| 759 | 762 |
| 763 void emitRuntimeClassesAndTests(CodeBuffer buffer) { |
| 764 JavaScriptBackend backend = compiler.backend; |
| 765 RuntimeTypeInformation rti = backend.rti; |
| 766 |
| 767 TypeChecks typeChecks = rti.computeRequiredChecks(); |
| 768 |
| 769 bool needsHolder(ClassElement cls) { |
| 770 return !neededClasses.contains(cls) || cls.isNative() || |
| 771 rti.isJsNative(cls); |
| 772 } |
| 773 |
| 774 void maybeGenerateHolder(ClassElement cls) { |
| 775 if (!needsHolder(cls)) return; |
| 776 |
| 777 String holder = namer.isolateAccess(cls); |
| 778 String name = namer.getName(cls); |
| 779 buffer.add("$holder$_=$_{builtin\$cls:$_'$name'"); |
| 780 for (ClassElement check in typeChecks[cls]) { |
| 781 buffer.add(',$_${namer.operatorIs(check)}:${_}true'); |
| 782 }; |
| 783 buffer.add('}$N'); |
| 784 } |
| 785 |
| 786 // Create representation objects for classes that we do not have a class |
| 787 // definition for (because they are uninstantiated or native). |
| 788 for (ClassElement cls in rti.allArguments) { |
| 789 maybeGenerateHolder(cls); |
| 790 } |
| 791 |
| 792 // Add checks to the constructors of instantiated classes. |
| 793 for (ClassElement cls in typeChecks) { |
| 794 if (needsHolder(cls)) { |
| 795 // We already emitted the is-checks in the object definition for this |
| 796 // class. |
| 797 continue; |
| 798 } |
| 799 String holder = namer.isolateAccess(cls); |
| 800 for (ClassElement check in typeChecks[cls]) { |
| 801 buffer.add('$holder.${namer.operatorIs(check)}$_=${_}true$N'); |
| 802 }; |
| 803 } |
| 804 } |
| 805 |
| 760 /** | 806 /** |
| 761 * Documentation wanted -- johnniwinther | 807 * Documentation wanted -- johnniwinther |
| 762 * | 808 * |
| 763 * Invariant: [classElement] must be a declaration element. | 809 * Invariant: [classElement] must be a declaration element. |
| 764 */ | 810 */ |
| 765 void visitClassFields(ClassElement classElement, | 811 void visitClassFields(ClassElement classElement, |
| 766 void addField(Element member, | 812 void addField(Element member, |
| 767 String name, | 813 String name, |
| 768 String accessorName, | 814 String accessorName, |
| 769 bool needsGetter, | 815 bool needsGetter, |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1174 } | 1220 } |
| 1175 } | 1221 } |
| 1176 | 1222 |
| 1177 return (ClassElement cls) => !unneededClasses.contains(cls); | 1223 return (ClassElement cls) => !unneededClasses.contains(cls); |
| 1178 } | 1224 } |
| 1179 | 1225 |
| 1180 void emitClasses(CodeBuffer buffer) { | 1226 void emitClasses(CodeBuffer buffer) { |
| 1181 // Compute the required type checks to know which classes need a | 1227 // Compute the required type checks to know which classes need a |
| 1182 // 'is$' method. | 1228 // 'is$' method. |
| 1183 computeRequiredTypeChecks(); | 1229 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 = | 1230 List<ClassElement> sortedClasses = |
| 1200 new List<ClassElement>.from(neededClasses); | 1231 new List<ClassElement>.from(neededClasses); |
| 1201 sortedClasses.sort((ClassElement class1, ClassElement class2) { | 1232 sortedClasses.sort((ClassElement class1, ClassElement class2) { |
| 1202 // We sort by the ids of the classes. There is no guarantee that these | 1233 // 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 | 1234 // ids are meaningful (or even deterministic), but in the current |
| 1204 // implementation they are increasing within a source file. | 1235 // implementation they are increasing within a source file. |
| 1205 return class1.id - class2.id; | 1236 return class1.id - class2.id; |
| 1206 }); | 1237 }); |
| 1207 | 1238 |
| 1208 // If we need noSuchMethod support, we run through all needed | 1239 // 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) { | 1963 for (ClassElement cls in classes) { |
| 1933 if (compiler.codegenWorld.instantiatedClasses.contains(cls)) { | 1964 if (compiler.codegenWorld.instantiatedClasses.contains(cls)) { |
| 1934 buffer.add('\n$_$_'); | 1965 buffer.add('\n$_$_'); |
| 1935 emitInterceptorCheck(cls, buffer); | 1966 emitInterceptorCheck(cls, buffer); |
| 1936 } | 1967 } |
| 1937 } | 1968 } |
| 1938 buffer.add('\n$_${_}return $objectName.prototype;$n}$N'); | 1969 buffer.add('\n$_${_}return $objectName.prototype;$n}$N'); |
| 1939 }); | 1970 }); |
| 1940 } | 1971 } |
| 1941 | 1972 |
| 1973 void computeNeededClasses() { |
| 1974 instantiatedClasses = |
| 1975 compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter()); |
| 1976 neededClasses = new Set<ClassElement>.from(instantiatedClasses); |
| 1977 for (ClassElement element in instantiatedClasses) { |
| 1978 for (ClassElement superclass = element.superclass; |
| 1979 superclass != null; |
| 1980 superclass = superclass.superclass) { |
| 1981 if (neededClasses.contains(superclass)) break; |
| 1982 neededClasses.add(superclass); |
| 1983 } |
| 1984 } |
| 1985 } |
| 1986 |
| 1942 String assembleProgram() { | 1987 String assembleProgram() { |
| 1943 measure(() { | 1988 measure(() { |
| 1989 computeNeededClasses(); |
| 1990 |
| 1944 mainBuffer.add(GENERATED_BY); | 1991 mainBuffer.add(GENERATED_BY); |
| 1945 if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE); | 1992 if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE); |
| 1946 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); | 1993 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); |
| 1947 mainBuffer.add('init()$N$n'); | 1994 mainBuffer.add('init()$N$n'); |
| 1948 // Shorten the code by using "$$" as temporary. | 1995 // Shorten the code by using "$$" as temporary. |
| 1949 classesCollector = r"$$"; | 1996 classesCollector = r"$$"; |
| 1950 mainBuffer.add('var $classesCollector$_=$_{}$N'); | 1997 mainBuffer.add('var $classesCollector$_=$_{}$N'); |
| 1951 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. | 1998 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. |
| 1952 isolateProperties = namer.CURRENT_ISOLATE; | 1999 isolateProperties = namer.CURRENT_ISOLATE; |
| 1953 mainBuffer.add( | 2000 mainBuffer.add( |
| 1954 'var $isolateProperties$_=$_$isolatePropertiesName$N'); | 2001 'var $isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1955 emitClasses(mainBuffer); | 2002 emitClasses(mainBuffer); |
| 1956 mainBuffer.add(boundClosureBuffer); | 2003 mainBuffer.add(boundClosureBuffer); |
| 1957 // Clear the buffer, so that we can reuse it for the native classes. | 2004 // Clear the buffer, so that we can reuse it for the native classes. |
| 1958 boundClosureBuffer.clear(); | 2005 boundClosureBuffer.clear(); |
| 1959 emitStaticFunctions(mainBuffer); | 2006 emitStaticFunctions(mainBuffer); |
| 1960 emitStaticFunctionGetters(mainBuffer); | 2007 emitStaticFunctionGetters(mainBuffer); |
| 1961 // We need to finish the classes before we construct compile time | 2008 // We need to finish the classes before we construct compile time |
| 1962 // constants. | 2009 // constants. |
| 1963 emitFinishClassesInvocationIfNecessary(mainBuffer); | 2010 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 2011 emitRuntimeClassesAndTests(mainBuffer); |
| 1964 emitCompileTimeConstants(mainBuffer); | 2012 emitCompileTimeConstants(mainBuffer); |
| 1965 // Static field initializations require the classes and compile-time | 2013 // Static field initializations require the classes and compile-time |
| 1966 // constants to be set up. | 2014 // constants to be set up. |
| 1967 emitStaticNonFinalFieldInitializations(mainBuffer); | 2015 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 1968 emitGetInterceptorMethods(mainBuffer); | 2016 emitGetInterceptorMethods(mainBuffer); |
| 1969 emitLazilyInitializedStaticFields(mainBuffer); | 2017 emitLazilyInitializedStaticFields(mainBuffer); |
| 1970 | 2018 |
| 1971 isolateProperties = isolatePropertiesName; | 2019 isolateProperties = isolatePropertiesName; |
| 1972 // The following code should not use the short-hand for the | 2020 // The following code should not use the short-hand for the |
| 1973 // initialStatics. | 2021 // initialStatics. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2019 """; | 2067 """; |
| 2020 const String HOOKS_API_USAGE = """ | 2068 const String HOOKS_API_USAGE = """ |
| 2021 // The code supports the following hooks: | 2069 // The code supports the following hooks: |
| 2022 // dartPrint(message) - if this function is defined it is called | 2070 // dartPrint(message) - if this function is defined it is called |
| 2023 // instead of the Dart [print] method. | 2071 // instead of the Dart [print] method. |
| 2024 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2072 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2025 // method will not be invoked directly. | 2073 // method will not be invoked directly. |
| 2026 // Instead, a closure that will invoke [main] is | 2074 // Instead, a closure that will invoke [main] is |
| 2027 // passed to [dartMainRunner]. | 2075 // passed to [dartMainRunner]. |
| 2028 """; | 2076 """; |
| OLD | NEW |