| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 */ | 52 */ |
| 53 final Map<int, String> boundClosureCache; | 53 final Map<int, String> boundClosureCache; |
| 54 | 54 |
| 55 /** | 55 /** |
| 56 * A cache of closures that are used to closurize instance methods | 56 * A cache of closures that are used to closurize instance methods |
| 57 * of interceptors. These closures are dynamically bound to the | 57 * of interceptors. These closures are dynamically bound to the |
| 58 * interceptor instance, and the actual receiver of the method. | 58 * interceptor instance, and the actual receiver of the method. |
| 59 */ | 59 */ |
| 60 final Map<int, String> interceptorClosureCache; | 60 final Map<int, String> interceptorClosureCache; |
| 61 Set<ClassElement> checkedClasses; | 61 Set<ClassElement> checkedClasses; |
| 62 Set<TypedefElement> checkedTypedefs; |
| 62 | 63 |
| 63 final bool generateSourceMap; | 64 final bool generateSourceMap; |
| 64 | 65 |
| 65 CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap) | 66 CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap) |
| 66 : boundClosureBuffer = new CodeBuffer(), | 67 : boundClosureBuffer = new CodeBuffer(), |
| 67 mainBuffer = new CodeBuffer(), | 68 mainBuffer = new CodeBuffer(), |
| 68 this.namer = namer, | 69 this.namer = namer, |
| 69 boundClosureCache = new Map<int, String>(), | 70 boundClosureCache = new Map<int, String>(), |
| 70 interceptorClosureCache = new Map<int, String>(), | 71 interceptorClosureCache = new Map<int, String>(), |
| 71 constantEmitter = new ConstantEmitter(compiler, namer), | 72 constantEmitter = new ConstantEmitter(compiler, namer), |
| 72 super(compiler) { | 73 super(compiler) { |
| 73 nativeEmitter = new NativeEmitter(this); | 74 nativeEmitter = new NativeEmitter(this); |
| 74 } | 75 } |
| 75 | 76 |
| 76 void computeRequiredTypeChecks() { | 77 void computeRequiredTypeChecks() { |
| 77 assert(checkedClasses == null); | 78 assert(checkedClasses == null); |
| 78 checkedClasses = new Set<ClassElement>(); | 79 checkedClasses = new Set<ClassElement>(); |
| 80 checkedTypedefs = new Set<TypedefElement>(); |
| 79 compiler.codegenWorld.isChecks.forEach((DartType t) { | 81 compiler.codegenWorld.isChecks.forEach((DartType t) { |
| 80 if (t is InterfaceType) checkedClasses.add(t.element); | 82 if (t is InterfaceType) { |
| 83 checkedClasses.add(t.element); |
| 84 } else if (t is TypedefType) { |
| 85 checkedTypedefs.add(t.element); |
| 86 } |
| 81 }); | 87 }); |
| 82 } | 88 } |
| 83 | 89 |
| 84 js.Expression constantReference(Constant value) { | 90 js.Expression constantReference(Constant value) { |
| 85 return constantEmitter.reference(value); | 91 return constantEmitter.reference(value); |
| 86 } | 92 } |
| 87 | 93 |
| 88 js.Expression constantInitializerExpression(Constant value) { | 94 js.Expression constantInitializerExpression(Constant value) { |
| 89 return constantEmitter.initializationExpression(value); | 95 return constantEmitter.initializationExpression(value); |
| 90 } | 96 } |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 | 692 |
| 687 classElement.implementation.forEachMember( | 693 classElement.implementation.forEachMember( |
| 688 (ClassElement enclosing, Element member) { | 694 (ClassElement enclosing, Element member) { |
| 689 assert(invariant(classElement, member.isDeclaration)); | 695 assert(invariant(classElement, member.isDeclaration)); |
| 690 if (member.isInstanceMember()) { | 696 if (member.isInstanceMember()) { |
| 691 addInstanceMember(member, defineInstanceMember); | 697 addInstanceMember(member, defineInstanceMember); |
| 692 } | 698 } |
| 693 }, | 699 }, |
| 694 includeBackendMembers: true); | 700 includeBackendMembers: true); |
| 695 | 701 |
| 696 generateIsTestsOn(classElement, (ClassElement other) { | 702 generateIsTestsOn(classElement, (Element other) { |
| 697 String code; | 703 String code; |
| 698 if (other.isObject(compiler)) return; | 704 if (compiler.objectClass == other) return; |
| 699 if (nativeEmitter.requiresNativeIsCheck(other)) { | 705 if (nativeEmitter.requiresNativeIsCheck(other)) { |
| 700 code = 'function() { return true; }'; | 706 code = 'function() { return true; }'; |
| 701 } else { | 707 } else { |
| 702 code = 'true'; | 708 code = 'true'; |
| 703 } | 709 } |
| 704 CodeBuffer typeTestBuffer = new CodeBuffer(); | 710 CodeBuffer typeTestBuffer = new CodeBuffer(); |
| 705 typeTestBuffer.add(code); | 711 typeTestBuffer.add(code); |
| 706 defineInstanceMember(namer.operatorIs(other), typeTestBuffer); | 712 defineInstanceMember(namer.operatorIs(other), typeTestBuffer); |
| 707 }); | 713 }); |
| 708 | 714 |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 defineInstanceMember(name, code); | 1022 defineInstanceMember(name, code); |
| 1017 } | 1023 } |
| 1018 } | 1024 } |
| 1019 | 1025 |
| 1020 /** | 1026 /** |
| 1021 * Generate "is tests" for [cls]: itself, and the "is tests" for the | 1027 * Generate "is tests" for [cls]: itself, and the "is tests" for the |
| 1022 * classes it implements. We don't need to add the "is tests" of the | 1028 * classes it implements. We don't need to add the "is tests" of the |
| 1023 * super class because they will be inherited at runtime. | 1029 * super class because they will be inherited at runtime. |
| 1024 */ | 1030 */ |
| 1025 void generateIsTestsOn(ClassElement cls, | 1031 void generateIsTestsOn(ClassElement cls, |
| 1026 void emitIsTest(ClassElement element)) { | 1032 void emitIsTest(Element element)) { |
| 1027 if (checkedClasses.contains(cls)) { | 1033 if (checkedClasses.contains(cls)) { |
| 1028 emitIsTest(cls); | 1034 emitIsTest(cls); |
| 1029 } | 1035 } |
| 1036 |
| 1030 Set<Element> generated = new Set<Element>(); | 1037 Set<Element> generated = new Set<Element>(); |
| 1031 // A class that defines a [:call:] method implicitly implements | 1038 // A class that defines a [:call:] method implicitly implements |
| 1032 // [Function]. | 1039 // [Function] and needs checks for all typedefs that are used in is-checks. |
| 1033 if (checkedClasses.contains(compiler.functionClass) | 1040 if (checkedClasses.contains(compiler.functionClass) || |
| 1034 && cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME) != null) { | 1041 !checkedTypedefs.isEmpty) { |
| 1035 generateInterfacesIsTests(compiler.functionClass, emitIsTest, generated); | 1042 FunctionElement call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME); |
| 1043 if (call != null) { |
| 1044 generateInterfacesIsTests(compiler.functionClass, |
| 1045 emitIsTest, |
| 1046 generated); |
| 1047 FunctionType callType = call.computeType(compiler); |
| 1048 for (TypedefElement typedef in checkedTypedefs) { |
| 1049 FunctionType typedefType = |
| 1050 typedef.computeType(compiler).unalias(compiler); |
| 1051 if (compiler.types.isSubtype(callType, typedefType)) { |
| 1052 emitIsTest(typedef); |
| 1053 } |
| 1054 } |
| 1055 } |
| 1036 } | 1056 } |
| 1037 for (DartType interfaceType in cls.interfaces) { | 1057 for (DartType interfaceType in cls.interfaces) { |
| 1038 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); | 1058 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); |
| 1039 } | 1059 } |
| 1040 } | 1060 } |
| 1041 | 1061 |
| 1042 /** | 1062 /** |
| 1043 * Generate "is tests" where [cls] is being implemented. | 1063 * Generate "is tests" where [cls] is being implemented. |
| 1044 */ | 1064 */ |
| 1045 void generateInterfacesIsTests(ClassElement cls, | 1065 void generateInterfacesIsTests(ClassElement cls, |
| (...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1871 const String HOOKS_API_USAGE = """ | 1891 const String HOOKS_API_USAGE = """ |
| 1872 // Generated by dart2js, the Dart to JavaScript compiler. | 1892 // Generated by dart2js, the Dart to JavaScript compiler. |
| 1873 // The code supports the following hooks: | 1893 // The code supports the following hooks: |
| 1874 // dartPrint(message) - if this function is defined it is called | 1894 // dartPrint(message) - if this function is defined it is called |
| 1875 // instead of the Dart [print] method. | 1895 // instead of the Dart [print] method. |
| 1876 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1896 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 1877 // method will not be invoked directly. | 1897 // method will not be invoked directly. |
| 1878 // Instead, a closure that will invoke [main] is | 1898 // Instead, a closure that will invoke [main] is |
| 1879 // passed to [dartMainRunner]. | 1899 // passed to [dartMainRunner]. |
| 1880 """; | 1900 """; |
| OLD | NEW |