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 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 728 void emitInstanceMembers(ClassElement classElement, | 728 void emitInstanceMembers(ClassElement classElement, |
| 729 ClassBuilder builder) { | 729 ClassBuilder builder) { |
| 730 assert(invariant(classElement, classElement.isDeclaration)); | 730 assert(invariant(classElement, classElement.isDeclaration)); |
| 731 JavaScriptBackend backend = compiler.backend; | 731 JavaScriptBackend backend = compiler.backend; |
| 732 if (classElement == backend.objectInterceptorClass) { | 732 if (classElement == backend.objectInterceptorClass) { |
| 733 emitInterceptorMethods(builder); | 733 emitInterceptorMethods(builder); |
| 734 // The ObjectInterceptor does not have any instance methods. | 734 // The ObjectInterceptor does not have any instance methods. |
| 735 return; | 735 return; |
| 736 } | 736 } |
| 737 | 737 |
| 738 void visitMember(ClassElement enclosing, Element member) { | |
| 739 assert(invariant(classElement, member.isDeclaration)); | |
| 740 if (member.isInstanceMember()) { | |
| 741 addInstanceMember(member, builder); | |
| 742 } | |
| 743 } | |
| 744 | |
| 745 // TODO(kasperl): We should make sure to only emit one version of | |
| 746 // overridden methods. Right now, we rely on the ordering so the | |
| 747 // methods pulled in from mixins are replaced with the members | |
| 748 // from the class definition. | |
| 749 | |
| 750 // If the class is a native class, we have to add the instance | |
| 751 // members defined in the non-native mixin applications used by | |
| 752 // the class. | |
| 753 visitNativeMixins(classElement, (MixinApplicationElement mixin) { | |
|
ngeoffray
2013/01/24 11:55:53
visitMixinsOfNativeClasses?
| |
| 754 mixin.forEachMember( | |
| 755 visitMember, | |
| 756 includeBackendMembers: true, | |
| 757 includeSuperMembers: false); | |
| 758 }); | |
| 759 | |
| 738 classElement.implementation.forEachMember( | 760 classElement.implementation.forEachMember( |
| 739 (ClassElement enclosing, Element member) { | 761 visitMember, |
| 740 assert(invariant(classElement, member.isDeclaration)); | 762 includeBackendMembers: true, |
| 741 if (member.isInstanceMember()) { | 763 includeSuperMembers: false); |
| 742 addInstanceMember(member, builder); | |
| 743 } | |
| 744 }, | |
| 745 includeBackendMembers: true); | |
| 746 | 764 |
| 747 generateIsTestsOn(classElement, (Element other) { | 765 generateIsTestsOn(classElement, (Element other) { |
| 748 js.Expression code; | 766 js.Expression code; |
| 749 if (compiler.objectClass == other) return; | 767 if (compiler.objectClass == other) return; |
| 750 if (nativeEmitter.requiresNativeIsCheck(other)) { | 768 if (nativeEmitter.requiresNativeIsCheck(other)) { |
| 751 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true)))); | 769 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true)))); |
| 752 } else { | 770 } else { |
| 753 code = new js.LiteralBool(true); | 771 code = new js.LiteralBool(true); |
| 754 } | 772 } |
| 755 builder.addProperty(namer.operatorIs(other), code); | 773 builder.addProperty(namer.operatorIs(other), code); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 819 // class. | 837 // class. |
| 820 continue; | 838 continue; |
| 821 } | 839 } |
| 822 String holder = namer.isolateAccess(cls); | 840 String holder = namer.isolateAccess(cls); |
| 823 for (ClassElement check in typeChecks[cls]) { | 841 for (ClassElement check in typeChecks[cls]) { |
| 824 buffer.add('$holder.${namer.operatorIs(check)}$_=${_}true$N'); | 842 buffer.add('$holder.${namer.operatorIs(check)}$_=${_}true$N'); |
| 825 }; | 843 }; |
| 826 } | 844 } |
| 827 } | 845 } |
| 828 | 846 |
| 847 void visitNativeMixins(ClassElement classElement, | |
| 848 void visit(MixinApplicationElement mixinApplication)) { | |
| 849 if (!classElement.isNative()) return; | |
| 850 // Use recursion to make sure to visit the superclasses before the | |
| 851 // subclasses. Once we start keeping track of the emitted fields | |
| 852 // and members, we're going to want to visit these in the other | |
| 853 // order so we get the most specialized definition first. | |
| 854 void recurse(ClassElement cls) { | |
| 855 if (cls == null || !cls.isMixinApplication) return; | |
| 856 recurse(cls.superclass); | |
| 857 assert(!cls.isNative()); | |
| 858 visit(cls); | |
| 859 } | |
| 860 recurse(classElement.superclass); | |
| 861 } | |
| 862 | |
| 829 /** | 863 /** |
| 830 * Documentation wanted -- johnniwinther | 864 * Documentation wanted -- johnniwinther |
| 831 * | 865 * |
| 832 * Invariant: [classElement] must be a declaration element. | 866 * Invariant: [classElement] must be a declaration element. |
| 833 */ | 867 */ |
| 834 void visitClassFields(ClassElement classElement, | 868 void visitClassFields(ClassElement classElement, |
| 835 void addField(Element member, | 869 void addField(Element member, |
| 836 String name, | 870 String name, |
| 837 String accessorName, | 871 String accessorName, |
| 838 bool needsGetter, | 872 bool needsGetter, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 884 // Getters and setters with suffixes will be generated dynamically. | 918 // Getters and setters with suffixes will be generated dynamically. |
| 885 addField(member, | 919 addField(member, |
| 886 fieldName, | 920 fieldName, |
| 887 accessorName, | 921 accessorName, |
| 888 needsGetter, | 922 needsGetter, |
| 889 needsSetter, | 923 needsSetter, |
| 890 needsCheckedSetter); | 924 needsCheckedSetter); |
| 891 } | 925 } |
| 892 } | 926 } |
| 893 | 927 |
| 928 // TODO(kasperl): We should make sure to only emit one version of | |
| 929 // overridden fields. Right now, we rely on the ordering so the | |
| 930 // fields pulled in from mixins are replaced with the fields from | |
| 931 // the class definition. | |
| 932 | |
| 933 // If the class is a native class, we have to add the fields | |
| 934 // defined in the non-native mixin applications used by the class. | |
| 935 visitNativeMixins(classElement, (MixinApplicationElement mixin) { | |
| 936 mixin.forEachInstanceField( | |
| 937 visitField, | |
| 938 includeBackendMembers: true, | |
| 939 includeSuperMembers: false); | |
| 940 }); | |
| 941 | |
| 894 // If a class is not instantiated then we add the field just so we can | 942 // If a class is not instantiated then we add the field just so we can |
| 895 // generate the field getter/setter dynamically. Since this is only | 943 // generate the field getter/setter dynamically. Since this is only |
| 896 // allowed on fields that are in [classElement] we don't need to visit | 944 // allowed on fields that are in [classElement] we don't need to visit |
| 897 // superclasses for non-instantiated classes. | 945 // superclasses for non-instantiated classes. |
| 898 classElement.implementation.forEachInstanceField( | 946 classElement.implementation.forEachInstanceField( |
| 899 visitField, | 947 visitField, |
| 900 includeBackendMembers: true, | 948 includeBackendMembers: true, |
| 901 includeSuperMembers: isInstantiated && !classElement.isNative()); | 949 includeSuperMembers: isInstantiated && !classElement.isNative()); |
| 902 } | 950 } |
| 903 | 951 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1061 return; | 1109 return; |
| 1062 } else { | 1110 } else { |
| 1063 // TODO(ngeoffray): Instead of switching between buffer, we | 1111 // TODO(ngeoffray): Instead of switching between buffer, we |
| 1064 // should create code sections, and decide where to emit them at | 1112 // should create code sections, and decide where to emit them at |
| 1065 // the end. | 1113 // the end. |
| 1066 buffer = mainBuffer; | 1114 buffer = mainBuffer; |
| 1067 } | 1115 } |
| 1068 | 1116 |
| 1069 needsDefineClass = true; | 1117 needsDefineClass = true; |
| 1070 String className = namer.getName(classElement); | 1118 String className = namer.getName(classElement); |
| 1119 | |
| 1120 // Find the first non-native superclass. | |
| 1071 ClassElement superclass = classElement.superclass; | 1121 ClassElement superclass = classElement.superclass; |
| 1122 while (superclass != null && superclass.isNative()) { | |
| 1123 superclass = superclass.superclass; | |
| 1124 } | |
| 1125 | |
| 1072 String superName = ""; | 1126 String superName = ""; |
| 1073 if (superclass != null) { | 1127 if (superclass != null) { |
| 1074 superName = namer.getName(superclass); | 1128 superName = namer.getName(superclass); |
| 1075 } | 1129 } |
| 1076 | 1130 |
| 1077 ClassBuilder builder = new ClassBuilder(); | 1131 ClassBuilder builder = new ClassBuilder(); |
| 1078 | 1132 |
| 1079 emitClassConstructor(classElement, builder); | 1133 emitClassConstructor(classElement, builder); |
| 1080 emitSuper(superName, builder); | 1134 emitSuper(superName, builder); |
| 1081 emitClassFields(classElement, builder, | 1135 emitClassFields(classElement, builder, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1155 // If [cls] is a closure, it has a synthetic call operator method. | 1209 // If [cls] is a closure, it has a synthetic call operator method. |
| 1156 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); | 1210 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); |
| 1157 } | 1211 } |
| 1158 if (call != null) { | 1212 if (call != null) { |
| 1159 generateInterfacesIsTests(compiler.functionClass, | 1213 generateInterfacesIsTests(compiler.functionClass, |
| 1160 emitIsTest, | 1214 emitIsTest, |
| 1161 generated); | 1215 generated); |
| 1162 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest); | 1216 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest); |
| 1163 } | 1217 } |
| 1164 } | 1218 } |
| 1219 | |
| 1165 for (DartType interfaceType in cls.interfaces) { | 1220 for (DartType interfaceType in cls.interfaces) { |
| 1166 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); | 1221 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); |
| 1167 } | 1222 } |
| 1223 | |
| 1224 // For native classes, we also have to run through their mixin | |
| 1225 // applications and make sure we deal with 'is' tests correctly | |
| 1226 // for those. | |
| 1227 visitNativeMixins(cls, (MixinApplicationElement mixin) { | |
| 1228 for (DartType interfaceType in mixin.interfaces) { | |
| 1229 ClassElement interfaceElement = interfaceType.element; | |
| 1230 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); | |
| 1231 } | |
| 1232 }); | |
| 1168 } | 1233 } |
| 1169 | 1234 |
| 1170 /** | 1235 /** |
| 1171 * Generate "is tests" where [cls] is being implemented. | 1236 * Generate "is tests" where [cls] is being implemented. |
| 1172 */ | 1237 */ |
| 1173 void generateInterfacesIsTests(ClassElement cls, | 1238 void generateInterfacesIsTests(ClassElement cls, |
| 1174 void emitIsTest(ClassElement element), | 1239 void emitIsTest(ClassElement element), |
| 1175 Set<Element> alreadyGenerated) { | 1240 Set<Element> alreadyGenerated) { |
| 1176 void tryEmitTest(ClassElement cls) { | 1241 void tryEmitTest(ClassElement cls) { |
| 1177 if (!alreadyGenerated.contains(cls) && checkedClasses.contains(cls)) { | 1242 if (!alreadyGenerated.contains(cls) && checkedClasses.contains(cls)) { |
| (...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2178 """; | 2243 """; |
| 2179 const String HOOKS_API_USAGE = """ | 2244 const String HOOKS_API_USAGE = """ |
| 2180 // The code supports the following hooks: | 2245 // The code supports the following hooks: |
| 2181 // dartPrint(message) - if this function is defined it is called | 2246 // dartPrint(message) - if this function is defined it is called |
| 2182 // instead of the Dart [print] method. | 2247 // instead of the Dart [print] method. |
| 2183 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2248 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2184 // method will not be invoked directly. | 2249 // method will not be invoked directly. |
| 2185 // Instead, a closure that will invoke [main] is | 2250 // Instead, a closure that will invoke [main] is |
| 2186 // passed to [dartMainRunner]. | 2251 // passed to [dartMainRunner]. |
| 2187 """; | 2252 """; |
| OLD | NEW |