Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1808)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 11557010: Implement subtype checks on type arguments. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addres comments. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698