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

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

Issue 11478022: Implement is-checks with typedefs for callable objects. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698