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

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

Issue 12211012: Revert "Implement substitution for type variables." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 10 months 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 757 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 visitMember, 768 visitMember,
769 includeBackendMembers: true, 769 includeBackendMembers: true,
770 includeSuperMembers: false); 770 includeSuperMembers: false);
771 }); 771 });
772 772
773 classElement.implementation.forEachMember( 773 classElement.implementation.forEachMember(
774 visitMember, 774 visitMember,
775 includeBackendMembers: true, 775 includeBackendMembers: true,
776 includeSuperMembers: false); 776 includeSuperMembers: false);
777 777
778 void generateIsTest(Element other) { 778 generateIsTestsOn(classElement, (Element other) {
779 js.Expression code; 779 js.Expression code;
780 if (compiler.objectClass == other) return; 780 if (compiler.objectClass == other) return;
781 if (nativeEmitter.requiresNativeIsCheck(other)) { 781 if (nativeEmitter.requiresNativeIsCheck(other)) {
782 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true)))); 782 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true))));
783 } else { 783 } else {
784 code = new js.LiteralBool(true); 784 code = new js.LiteralBool(true);
785 } 785 }
786 builder.addProperty(namer.operatorIs(other), code); 786 builder.addProperty(namer.operatorIs(other), code);
787 } 787 });
788
789 void generateSubstitution(Element other, {bool emitNull: false}) {
790 RuntimeTypeInformation rti = backend.rti;
791 // TODO(karlklose): support typedefs with variables.
792 if (other.kind == ElementKind.CLASS) {
793 String substitution = rti.getSupertypeSubstitution(classElement, other,
794 alwaysGenerateFunction: true);
795 if (substitution != null) {
796 builder.addProperty(namer.substitutionName(other),
797 new js.LiteralExpression(substitution));
798 } else if (emitNull) {
799 builder.addProperty(namer.substitutionName(other),
800 new js.LiteralNull());
801 }
802 }
803 }
804
805 generateIsTestsOn(classElement, generateIsTest, generateSubstitution);
806 788
807 if (identical(classElement, compiler.objectClass) 789 if (identical(classElement, compiler.objectClass)
808 && compiler.enabledNoSuchMethod) { 790 && compiler.enabledNoSuchMethod) {
809 // Emit the noSuchMethod handlers on the Object prototype now, 791 // Emit the noSuchMethod handlers on the Object prototype now,
810 // so that the code in the dynamicFunction helper can find 792 // so that the code in the dynamicFunction helper can find
811 // them. Note that this helper is invoked before analyzing the 793 // them. Note that this helper is invoked before analyzing the
812 // full JS script. 794 // full JS script.
813 if (!nativeEmitter.handleNoSuchMethod) { 795 if (!nativeEmitter.handleNoSuchMethod) {
814 emitNoSuchMethodHandlers(builder.addProperty); 796 emitNoSuchMethodHandlers(builder.addProperty);
815 } 797 }
(...skipping 12 matching lines...) Expand all
828 ? js.equals 810 ? js.equals
829 : js.strictEquals; 811 : js.strictEquals;
830 builder.addProperty(name, js.fun(['receiver', 'a'], 812 builder.addProperty(name, js.fun(['receiver', 'a'],
831 js.block1(js.return_(kind(js.use('receiver'), js.use('a')))))); 813 js.block1(js.return_(kind(js.use('receiver'), js.use('a'))))));
832 } 814 }
833 } 815 }
834 816
835 void emitRuntimeClassesAndTests(CodeBuffer buffer) { 817 void emitRuntimeClassesAndTests(CodeBuffer buffer) {
836 JavaScriptBackend backend = compiler.backend; 818 JavaScriptBackend backend = compiler.backend;
837 RuntimeTypeInformation rti = backend.rti; 819 RuntimeTypeInformation rti = backend.rti;
838 TypeChecks typeChecks = rti.getRequiredChecks(); 820
821 TypeChecks typeChecks = rti.computeRequiredChecks();
839 822
840 bool needsHolder(ClassElement cls) { 823 bool needsHolder(ClassElement cls) {
841 return !neededClasses.contains(cls) || cls.isNative() || 824 return !neededClasses.contains(cls) || cls.isNative() ||
842 rti.isJsNative(cls); 825 rti.isJsNative(cls);
843 } 826 }
844 827
845 /**
846 * Generates a holder object if it is needed. A holder is a JavaScript
847 * object literal with a field [builtin$cls] that contains the name of the
848 * class as a string (just like object constructors do). The is-checks for
849 * the class are are added to the holder object later.
850 */
851 void maybeGenerateHolder(ClassElement cls) { 828 void maybeGenerateHolder(ClassElement cls) {
852 if (!needsHolder(cls)) return; 829 if (!needsHolder(cls)) return;
830
853 String holder = namer.isolateAccess(cls); 831 String holder = namer.isolateAccess(cls);
854 String name = namer.getName(cls); 832 String name = namer.getName(cls);
855 buffer.add("$holder$_=$_{builtin\$cls:$_'$name'"); 833 buffer.add("$holder$_=$_{builtin\$cls:$_'$name'");
834 for (ClassElement check in typeChecks[cls]) {
835 buffer.add(',$_${namer.operatorIs(check)}:${_}true');
836 };
856 buffer.add('}$N'); 837 buffer.add('}$N');
857 } 838 }
858 839
859 // Create representation objects for classes that we do not have a class 840 // Create representation objects for classes that we do not have a class
860 // definition for (because they are uninstantiated or native). 841 // definition for (because they are uninstantiated or native).
861 for (ClassElement cls in rti.allArguments) { 842 for (ClassElement cls in rti.allArguments) {
862 maybeGenerateHolder(cls); 843 maybeGenerateHolder(cls);
863 } 844 }
864 845
865 // Add checks to the constructors of instantiated classes or to the created 846 // Add checks to the constructors of instantiated classes.
866 // holder object.
867 for (ClassElement cls in typeChecks) { 847 for (ClassElement cls in typeChecks) {
848 if (needsHolder(cls)) {
849 // We already emitted the is-checks in the object definition for this
850 // class.
851 continue;
852 }
868 String holder = namer.isolateAccess(cls); 853 String holder = namer.isolateAccess(cls);
869 for (ClassElement check in typeChecks[cls]) { 854 for (ClassElement check in typeChecks[cls]) {
870 buffer.add('$holder.${namer.operatorIs(check)}$_=${_}true$N'); 855 buffer.add('$holder.${namer.operatorIs(check)}$_=${_}true$N');
871 String body = rti.getSupertypeSubstitution(cls, check);
872 if (body != null) {
873 buffer.add('$holder.${namer.substitutionName(check)}$_=${_}$body$N');
874 }
875 }; 856 };
876 } 857 }
877 } 858 }
878 859
879 void visitNativeMixins(ClassElement classElement, 860 void visitNativeMixins(ClassElement classElement,
880 void visit(MixinApplicationElement mixinApplication)) { 861 void visit(MixinApplicationElement mixinApplication)) {
881 if (!classElement.isNative()) return; 862 if (!classElement.isNative()) return;
882 // Use recursion to make sure to visit the superclasses before the 863 // Use recursion to make sure to visit the superclasses before the
883 // subclasses. Once we start keeping track of the emitted fields 864 // subclasses. Once we start keeping track of the emitted fields
884 // and members, we're going to want to visit these in the other 865 // and members, we're going to want to visit these in the other
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 FunctionType typedefType = 1217 FunctionType typedefType =
1237 typedef.computeType(compiler).unalias(compiler); 1218 typedef.computeType(compiler).unalias(compiler);
1238 return compiler.types.isSubtype(type, typedefType); 1219 return compiler.types.isSubtype(type, typedefType);
1239 } 1220 }
1240 return checkedTypedefs.where(isSubtype).toList() 1221 return checkedTypedefs.where(isSubtype).toList()
1241 ..sort(Elements.compareByPosition); 1222 ..sort(Elements.compareByPosition);
1242 } 1223 }
1243 1224
1244 /** 1225 /**
1245 * Generate "is tests" for [cls]: itself, and the "is tests" for the 1226 * Generate "is tests" for [cls]: itself, and the "is tests" for the
1246 * classes it implements and type argument substitution functions for these 1227 * classes it implements. We don't need to add the "is tests" of the
1247 * tests. We don't need to add the "is tests" of the super class because 1228 * super class because they will be inherited at runtime.
1248 * they will be inherited at runtime, but we may need to generate the
1249 * substitutions, because they may have changed.
1250 */ 1229 */
1251 void generateIsTestsOn(ClassElement cls, 1230 void generateIsTestsOn(ClassElement cls,
1252 void emitIsTest(Element element), 1231 void emitIsTest(Element element)) {
1253 void emitSubstitution(Element element, {emitNull})) {
1254 if (checkedClasses.contains(cls)) { 1232 if (checkedClasses.contains(cls)) {
1255 emitIsTest(cls); 1233 emitIsTest(cls);
1256 emitSubstitution(cls);
1257 }
1258
1259 JavaScriptBackend jsBackend = compiler.backend;
1260 RuntimeTypeInformation rti = jsBackend.rti;
1261 ClassElement superclass = cls.superclass;
1262
1263 bool haveSameTypeVariables(ClassElement a, ClassElement b) {
1264 if (a.isClosure()) return true;
1265 return a.typeVariables == b.typeVariables;
1266 }
1267
1268 if (superclass != null && superclass != compiler.objectClass &&
1269 !haveSameTypeVariables(cls, superclass)) {
1270 // We cannot inherit the generated substitutions, because the type
1271 // variable layout for this class is different. Instead we generate
1272 // substitutions for all checks and make emitSubstitution a NOP for the
1273 // rest of this function.
1274 for (ClassElement check in checkedClasses) {
1275 for (DartType supertype in cls.allSupertypes) {
1276 if (supertype.element == check) {
1277 // Generate substitution. If no substitution is necessary, emit
1278 // [:null:] to overwrite a (possibly) existing substitution from the
1279 // super classes.
1280 emitSubstitution(check, emitNull: true);
1281 }
1282 }
1283 }
1284 void emitNothing(_, {emitNull}) {};
1285 emitSubstitution = emitNothing;
1286 } 1234 }
1287 1235
1288 Set<Element> generated = new Set<Element>(); 1236 Set<Element> generated = new Set<Element>();
1289 // A class that defines a [:call:] method implicitly implements 1237 // A class that defines a [:call:] method implicitly implements
1290 // [Function] and needs checks for all typedefs that are used in is-checks. 1238 // [Function] and needs checks for all typedefs that are used in is-checks.
1291 if (checkedClasses.contains(compiler.functionClass) || 1239 if (checkedClasses.contains(compiler.functionClass) ||
1292 !checkedTypedefs.isEmpty) { 1240 !checkedTypedefs.isEmpty) {
1293 FunctionElement call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME); 1241 FunctionElement call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME);
1294 if (call == null) { 1242 if (call == null) {
1295 // If [cls] is a closure, it has a synthetic call operator method. 1243 // If [cls] is a closure, it has a synthetic call operator method.
1296 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); 1244 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME);
1297 } 1245 }
1298 if (call != null) { 1246 if (call != null) {
1299 generateInterfacesIsTests(compiler.functionClass, 1247 generateInterfacesIsTests(compiler.functionClass,
1300 emitIsTest, 1248 emitIsTest,
1301 emitSubstitution,
1302 generated); 1249 generated);
1303 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest); 1250 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest);
1304 } 1251 }
1305 } 1252 }
1306 1253
1307 for (DartType interfaceType in cls.interfaces) { 1254 for (DartType interfaceType in cls.interfaces) {
1308 generateInterfacesIsTests(interfaceType.element, emitIsTest, 1255 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated);
1309 emitSubstitution, generated);
1310 } 1256 }
1311 1257
1312 // For native classes, we also have to run through their mixin 1258 // For native classes, we also have to run through their mixin
1313 // applications and make sure we deal with 'is' tests correctly 1259 // applications and make sure we deal with 'is' tests correctly
1314 // for those. 1260 // for those.
1315 visitNativeMixins(cls, (MixinApplicationElement mixin) { 1261 visitNativeMixins(cls, (MixinApplicationElement mixin) {
1316 for (DartType interfaceType in mixin.interfaces) { 1262 for (DartType interfaceType in mixin.interfaces) {
1317 ClassElement interfaceElement = interfaceType.element; 1263 ClassElement interfaceElement = interfaceType.element;
1318 generateInterfacesIsTests(interfaceType.element, emitIsTest, 1264 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated);
1319 emitSubstitution, generated);
1320 } 1265 }
1321 }); 1266 });
1322 } 1267 }
1323 1268
1324 /** 1269 /**
1325 * Generate "is tests" where [cls] is being implemented. 1270 * Generate "is tests" where [cls] is being implemented.
1326 */ 1271 */
1327 void generateInterfacesIsTests(ClassElement cls, 1272 void generateInterfacesIsTests(ClassElement cls,
1328 void emitIsTest(ClassElement element), 1273 void emitIsTest(ClassElement element),
1329 void emitSubstitution(ClassElement element),
1330 Set<Element> alreadyGenerated) { 1274 Set<Element> alreadyGenerated) {
1331 void tryEmitTest(ClassElement check) { 1275 void tryEmitTest(ClassElement cls) {
1332 if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) { 1276 if (!alreadyGenerated.contains(cls) && checkedClasses.contains(cls)) {
1333 alreadyGenerated.add(check); 1277 alreadyGenerated.add(cls);
1334 emitIsTest(check); 1278 emitIsTest(cls);
1335 emitSubstitution(check);
1336 } 1279 }
1337 }; 1280 };
1338 1281
1339 tryEmitTest(cls); 1282 tryEmitTest(cls);
1340 1283
1341 for (DartType interfaceType in cls.interfaces) { 1284 for (DartType interfaceType in cls.interfaces) {
1342 Element element = interfaceType.element; 1285 Element element = interfaceType.element;
1343 tryEmitTest(element); 1286 tryEmitTest(element);
1344 generateInterfacesIsTests(element, emitIsTest, emitSubstitution, 1287 generateInterfacesIsTests(element, emitIsTest, alreadyGenerated);
1345 alreadyGenerated);
1346 } 1288 }
1347 1289
1348 // We need to also emit "is checks" for the superclass and its supertypes. 1290 // We need to also emit "is checks" for the superclass and its supertypes.
1349 ClassElement superclass = cls.superclass; 1291 ClassElement superclass = cls.superclass;
1350 if (superclass != null) { 1292 if (superclass != null) {
1351 tryEmitTest(superclass); 1293 tryEmitTest(superclass);
1352 generateInterfacesIsTests(superclass, emitIsTest, emitSubstitution, 1294 generateInterfacesIsTests(superclass, emitIsTest, alreadyGenerated);
1353 alreadyGenerated);
1354 } 1295 }
1355 } 1296 }
1356 1297
1357 /** 1298 /**
1358 * Return a function that returns true if its argument is a class 1299 * Return a function that returns true if its argument is a class
1359 * that needs to be emitted. 1300 * that needs to be emitted.
1360 */ 1301 */
1361 Function computeClassFilter() { 1302 Function computeClassFilter() {
1362 Set<ClassElement> unneededClasses = new Set<ClassElement>(); 1303 Set<ClassElement> unneededClasses = new Set<ClassElement>();
1363 // The [Bool] class is not marked as abstract, but has a factory 1304 // The [Bool] class is not marked as abstract, but has a factory
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after
2404 """; 2345 """;
2405 const String HOOKS_API_USAGE = """ 2346 const String HOOKS_API_USAGE = """
2406 // The code supports the following hooks: 2347 // The code supports the following hooks:
2407 // dartPrint(message) - if this function is defined it is called 2348 // dartPrint(message) - if this function is defined it is called
2408 // instead of the Dart [print] method. 2349 // instead of the Dart [print] method.
2409 // dartMainRunner(main) - if this function is defined, the Dart [main] 2350 // dartMainRunner(main) - if this function is defined, the Dart [main]
2410 // method will not be invoked directly. 2351 // method will not be invoked directly.
2411 // Instead, a closure that will invoke [main] is 2352 // Instead, a closure that will invoke [main] is
2412 // passed to [dartMainRunner]. 2353 // passed to [dartMainRunner].
2413 """; 2354 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698