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

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

Issue 12210142: Implement is-checks against type variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 9 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 100
101 /** 101 /**
102 * Raw Typedef symbols occuring in is-checks and type assertions. If the 102 * Raw Typedef symbols occuring in is-checks and type assertions. If the
103 * program contains `x is F<int>` and `x is F<bool>` then the TypedefElement 103 * program contains `x is F<int>` and `x is F<bool>` then the TypedefElement
104 * `F` will occur once in [checkedTypedefs]. 104 * `F` will occur once in [checkedTypedefs].
105 */ 105 */
106 Set<TypedefElement> checkedTypedefs; 106 Set<TypedefElement> checkedTypedefs;
107 107
108 final bool generateSourceMap; 108 final bool generateSourceMap;
109 109
110 Iterable<ClassElement> cachedClassesUsingTypeVariableTests;
111
112 Iterable<ClassElement> get classesUsingTypeVariableTests {
113 if (cachedClassesUsingTypeVariableTests == null) {
114 cachedClassesUsingTypeVariableTests = compiler.codegenWorld.isChecks
115 .where((DartType t) => t is TypeVariableType)
116 .map((TypeVariableType v) => v.element.getEnclosingClass())
117 .toList();
118 }
119 return cachedClassesUsingTypeVariableTests;
120 }
121
110 CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap) 122 CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap)
111 : boundClosureBuffer = new CodeBuffer(), 123 : boundClosureBuffer = new CodeBuffer(),
112 mainBuffer = new CodeBuffer(), 124 mainBuffer = new CodeBuffer(),
113 this.namer = namer, 125 this.namer = namer,
114 boundClosureCache = new Map<int, String>(), 126 boundClosureCache = new Map<int, String>(),
115 interceptorClosureCache = new Map<int, String>(), 127 interceptorClosureCache = new Map<int, String>(),
116 constantEmitter = new ConstantEmitter(compiler, namer), 128 constantEmitter = new ConstantEmitter(compiler, namer),
117 super(compiler) { 129 super(compiler) {
118 nativeEmitter = new NativeEmitter(this); 130 nativeEmitter = new NativeEmitter(this);
119 } 131 }
120 132
121 void computeRequiredTypeChecks() { 133 void computeRequiredTypeChecks() {
122 assert(checkedClasses == null); 134 assert(checkedClasses == null && checkedTypedefs == null);
135
136 compiler.codegenWorld.addImplicitChecks(classesUsingTypeVariableTests);
137
123 checkedClasses = new Set<ClassElement>(); 138 checkedClasses = new Set<ClassElement>();
124 checkedTypedefs = new Set<TypedefElement>(); 139 checkedTypedefs = new Set<TypedefElement>();
125 compiler.codegenWorld.isChecks.forEach((DartType t) { 140 compiler.codegenWorld.isChecks.forEach((DartType t) {
126 if (t is InterfaceType) { 141 if (t is InterfaceType) {
127 checkedClasses.add(t.element); 142 checkedClasses.add(t.element);
128 } else if (t is TypedefType) { 143 } else if (t is TypedefType) {
129 checkedTypedefs.add(t.element); 144 checkedTypedefs.add(t.element);
130 } 145 }
131 }); 146 });
132 } 147 }
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 includeSuperMembers: false); 1083 includeSuperMembers: false);
1069 }); 1084 });
1070 1085
1071 classElement.implementation.forEachMember( 1086 classElement.implementation.forEachMember(
1072 visitMember, 1087 visitMember,
1073 includeBackendMembers: true, 1088 includeBackendMembers: true,
1074 includeSuperMembers: false); 1089 includeSuperMembers: false);
1075 1090
1076 void generateIsTest(Element other) { 1091 void generateIsTest(Element other) {
1077 jsAst.Expression code; 1092 jsAst.Expression code;
1078 if (compiler.objectClass == other) return; 1093 if (other == compiler.objectClass && other != classElement) {
1094 » // Avoid emitting [:$isObject:] on all classes but [Object].
ngeoffray 2013/02/27 12:36:28 But will we? We're not adding anything on a class
karlklose 2013/02/27 16:11:32 We need this check, since we do not track the is-c
1095 » return;
ngeoffray 2013/02/27 12:36:28 Remove tabs.
karlklose 2013/02/27 16:11:32 Done.
1096 }
1079 if (nativeEmitter.requiresNativeIsCheck(other)) { 1097 if (nativeEmitter.requiresNativeIsCheck(other)) {
1080 code = js.fun([], [js.return_(true)]); 1098 code = js.fun([], [js.return_(true)]);
1081 } else { 1099 } else {
1082 code = new jsAst.LiteralBool(true); 1100 code = new jsAst.LiteralBool(true);
1083 } 1101 }
1084 builder.addProperty(namer.operatorIs(other), code); 1102 builder.addProperty(namer.operatorIs(other), code);
1085 } 1103 }
1086 1104
1087 void generateSubstitution(Element other, {bool emitNull: false}) { 1105 void generateSubstitution(Element other, {bool emitNull: false}) {
1088 RuntimeTypeInformation rti = backend.rti; 1106 RuntimeTypeInformation rti = backend.rti;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 String name = backend.namer.publicInstanceMethodNameByArity( 1147 String name = backend.namer.publicInstanceMethodNameByArity(
1130 const SourceString('=='), 1); 1148 const SourceString('=='), 1);
1131 Function kind = (classElement == backend.jsNullClass) 1149 Function kind = (classElement == backend.jsNullClass)
1132 ? js.equals 1150 ? js.equals
1133 : js.strictEquals; 1151 : js.strictEquals;
1134 builder.addProperty(name, js.fun(['receiver', 'a'], 1152 builder.addProperty(name, js.fun(['receiver', 'a'],
1135 js.block(js.return_(kind(js['receiver'], js['a']))))); 1153 js.block(js.return_(kind(js['receiver'], js['a'])))));
1136 } 1154 }
1137 } 1155 }
1138 1156
1139 void emitRuntimeClassesAndTests(CodeBuffer buffer) { 1157 void emitRuntimeTypeSupport(CodeBuffer buffer) {
1140 RuntimeTypeInformation rti = backend.rti; 1158 RuntimeTypeInformation rti = backend.rti;
1141 TypeChecks typeChecks = rti.getRequiredChecks(); 1159 TypeChecks typeChecks = rti.getRequiredChecks();
1142 1160
1161 /// Classes that are not instantiated and native classes need a holder
1162 /// object for their checks, because there will be no class defined for
1163 /// them.
1143 bool needsHolder(ClassElement cls) { 1164 bool needsHolder(ClassElement cls) {
1144 return !neededClasses.contains(cls) || cls.isNative() || 1165 return !neededClasses.contains(cls) || cls.isNative();
1145 rti.isJsNative(cls);
1146 } 1166 }
1147 1167
1148 /** 1168 /**
1149 * Generates a holder object if it is needed. A holder is a JavaScript 1169 * Generates a holder object if it is needed. A holder is a JavaScript
1150 * object literal with a field [builtin$cls] that contains the name of the 1170 * object literal with a field [builtin$cls] that contains the name of the
1151 * class as a string (just like object constructors do). The is-checks for 1171 * class as a string (just like object constructors do). The is-checks for
1152 * the class are are added to the holder object later. 1172 * the class are are added to the holder object later.
1153 */ 1173 */
1154 void maybeGenerateHolder(ClassElement cls) { 1174 void maybeGenerateHolder(ClassElement cls) {
1155 if (!needsHolder(cls)) return; 1175 if (!needsHolder(cls)) return;
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
1558 // substitutions for all checks and make emitSubstitution a NOP for the 1578 // substitutions for all checks and make emitSubstitution a NOP for the
1559 // rest of this function. 1579 // rest of this function.
1560 Set<ClassElement> emitted = new Set<ClassElement>(); 1580 Set<ClassElement> emitted = new Set<ClassElement>();
1561 // TODO(karlklose): move the computation of these checks to 1581 // TODO(karlklose): move the computation of these checks to
1562 // RuntimeTypeInformation. 1582 // RuntimeTypeInformation.
1563 if (compiler.world.needsRti(cls)) { 1583 if (compiler.world.needsRti(cls)) {
1564 emitSubstitution(superclass, emitNull: true); 1584 emitSubstitution(superclass, emitNull: true);
1565 emitted.add(superclass); 1585 emitted.add(superclass);
1566 } 1586 }
1567 for (DartType supertype in cls.allSupertypes) { 1587 for (DartType supertype in cls.allSupertypes) {
1588 ClassElement superclass = supertype.element;
1589 if (classesUsingTypeVariableTests.contains(superclass)) {
1590 emitSubstitution(superclass, emitNull: true);
1591 emitted.add(superclass);
1592 }
1568 for (ClassElement check in checkedClasses) { 1593 for (ClassElement check in checkedClasses) {
1569 if (supertype.element == check && !emitted.contains(check)) { 1594 if (supertype.element == check && !emitted.contains(check)) {
1570 // Generate substitution. If no substitution is necessary, emit 1595 // Generate substitution. If no substitution is necessary, emit
1571 // [:null:] to overwrite a (possibly) existing substitution from the 1596 // [:null:] to overwrite a (possibly) existing substitution from the
1572 // super classes. 1597 // super classes.
1573 emitSubstitution(check, emitNull: true); 1598 emitSubstitution(check, emitNull: true);
1574 emitted.add(check); 1599 emitted.add(check);
1575 } 1600 }
1576 } 1601 }
1577 } 1602 }
(...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after
2575 ..addAll(buildFinishIsolateConstructor()) 2600 ..addAll(buildFinishIsolateConstructor())
2576 ); 2601 );
2577 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( 2602 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration(
2578 new jsAst.VariableDeclaration('init'), fun); 2603 new jsAst.VariableDeclaration('init'), fun);
2579 buffer.add(jsAst.prettyPrint(decl, compiler).getText()); 2604 buffer.add(jsAst.prettyPrint(decl, compiler).getText());
2580 } 2605 }
2581 2606
2582 String assembleProgram() { 2607 String assembleProgram() {
2583 measure(() { 2608 measure(() {
2584 computeNeededClasses(); 2609 computeNeededClasses();
2585
2586 mainBuffer.add(GENERATED_BY); 2610 mainBuffer.add(GENERATED_BY);
2587 if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE); 2611 if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE);
2588 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); 2612 mainBuffer.add('function ${namer.isolateName}()$_{}\n');
2589 mainBuffer.add('init()$N$n'); 2613 mainBuffer.add('init()$N$n');
2590 // Shorten the code by using "$$" as temporary. 2614 // Shorten the code by using "$$" as temporary.
2591 classesCollector = r"$$"; 2615 classesCollector = r"$$";
2592 mainBuffer.add('var $classesCollector$_=$_{}$N'); 2616 mainBuffer.add('var $classesCollector$_=$_{}$N');
2593 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. 2617 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
2594 isolateProperties = namer.CURRENT_ISOLATE; 2618 isolateProperties = namer.CURRENT_ISOLATE;
2595 mainBuffer.add( 2619 mainBuffer.add(
2596 'var $isolateProperties$_=$_$isolatePropertiesName$N'); 2620 'var $isolateProperties$_=$_$isolatePropertiesName$N');
2597 emitClasses(mainBuffer); 2621 emitClasses(mainBuffer);
2598 mainBuffer.add(boundClosureBuffer); 2622 mainBuffer.add(boundClosureBuffer);
2599 // Clear the buffer, so that we can reuse it for the native classes. 2623 // Clear the buffer, so that we can reuse it for the native classes.
2600 boundClosureBuffer.clear(); 2624 boundClosureBuffer.clear();
2601 emitStaticFunctions(mainBuffer); 2625 emitStaticFunctions(mainBuffer);
2602 emitStaticFunctionGetters(mainBuffer); 2626 emitStaticFunctionGetters(mainBuffer);
2603 // We need to finish the classes before we construct compile time 2627 // We need to finish the classes before we construct compile time
2604 // constants. 2628 // constants.
2605 emitFinishClassesInvocationIfNecessary(mainBuffer); 2629 emitFinishClassesInvocationIfNecessary(mainBuffer);
2606 emitRuntimeClassesAndTests(mainBuffer); 2630 emitRuntimeTypeSupport(mainBuffer);
2607 emitCompileTimeConstants(mainBuffer); 2631 emitCompileTimeConstants(mainBuffer);
2608 // Static field initializations require the classes and compile-time 2632 // Static field initializations require the classes and compile-time
2609 // constants to be set up. 2633 // constants to be set up.
2610 emitStaticNonFinalFieldInitializations(mainBuffer); 2634 emitStaticNonFinalFieldInitializations(mainBuffer);
2611 emitOneShotInterceptors(mainBuffer); 2635 emitOneShotInterceptors(mainBuffer);
2612 emitGetInterceptorMethods(mainBuffer); 2636 emitGetInterceptorMethods(mainBuffer);
2613 emitLazilyInitializedStaticFields(mainBuffer); 2637 emitLazilyInitializedStaticFields(mainBuffer);
2614 2638
2615 isolateProperties = isolatePropertiesName; 2639 isolateProperties = isolatePropertiesName;
2616 // The following code should not use the short-hand for the 2640 // The following code should not use the short-hand for the
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2676 """; 2700 """;
2677 const String HOOKS_API_USAGE = """ 2701 const String HOOKS_API_USAGE = """
2678 // The code supports the following hooks: 2702 // The code supports the following hooks:
2679 // dartPrint(message) - if this function is defined it is called 2703 // dartPrint(message) - if this function is defined it is called
2680 // instead of the Dart [print] method. 2704 // instead of the Dart [print] method.
2681 // dartMainRunner(main) - if this function is defined, the Dart [main] 2705 // dartMainRunner(main) - if this function is defined, the Dart [main]
2682 // method will not be invoked directly. 2706 // method will not be invoked directly.
2683 // Instead, a closure that will invoke [main] is 2707 // Instead, a closure that will invoke [main] is
2684 // passed to [dartMainRunner]. 2708 // passed to [dartMainRunner].
2685 """; 2709 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698