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

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: Fix a long line. 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 addComment(String comment, CodeBuffer buffer) { 133 void addComment(String comment, CodeBuffer buffer) {
122 buffer.add(jsAst.prettyPrint(js.comment(comment), compiler)); 134 buffer.add(jsAst.prettyPrint(js.comment(comment), compiler));
123 } 135 }
124 136
125 void computeRequiredTypeChecks() { 137 void computeRequiredTypeChecks() {
126 assert(checkedClasses == null); 138 assert(checkedClasses == null && checkedTypedefs == null);
139
140 compiler.codegenWorld.addImplicitChecks(classesUsingTypeVariableTests);
141
127 checkedClasses = new Set<ClassElement>(); 142 checkedClasses = new Set<ClassElement>();
128 checkedTypedefs = new Set<TypedefElement>(); 143 checkedTypedefs = new Set<TypedefElement>();
129 compiler.codegenWorld.isChecks.forEach((DartType t) { 144 compiler.codegenWorld.isChecks.forEach((DartType t) {
130 if (t is InterfaceType) { 145 if (t is InterfaceType) {
131 checkedClasses.add(t.element); 146 checkedClasses.add(t.element);
132 } else if (t is TypedefType) { 147 } else if (t is TypedefType) {
133 checkedTypedefs.add(t.element); 148 checkedTypedefs.add(t.element);
134 } 149 }
135 }); 150 });
136 } 151 }
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 includeSuperMembers: false); 940 includeSuperMembers: false);
926 }); 941 });
927 942
928 classElement.implementation.forEachMember( 943 classElement.implementation.forEachMember(
929 visitMember, 944 visitMember,
930 includeBackendMembers: true, 945 includeBackendMembers: true,
931 includeSuperMembers: false); 946 includeSuperMembers: false);
932 947
933 void generateIsTest(Element other) { 948 void generateIsTest(Element other) {
934 jsAst.Expression code; 949 jsAst.Expression code;
935 if (compiler.objectClass == other) return; 950 if (other == compiler.objectClass && other != classElement) {
951 // Avoid emitting [:$isObject:] on all classes but [Object].
952 return;
953 }
936 if (nativeEmitter.requiresNativeIsCheck(other)) { 954 if (nativeEmitter.requiresNativeIsCheck(other)) {
937 code = js.fun([], [js.return_(true)]); 955 code = js.fun([], [js.return_(true)]);
938 } else { 956 } else {
939 code = new jsAst.LiteralBool(true); 957 code = new jsAst.LiteralBool(true);
940 } 958 }
941 builder.addProperty(namer.operatorIs(other), code); 959 builder.addProperty(namer.operatorIs(other), code);
942 } 960 }
943 961
944 void generateSubstitution(Element other, {bool emitNull: false}) { 962 void generateSubstitution(Element other, {bool emitNull: false}) {
945 RuntimeTypeInformation rti = backend.rti; 963 RuntimeTypeInformation rti = backend.rti;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 String name = backend.namer.publicInstanceMethodNameByArity( 1004 String name = backend.namer.publicInstanceMethodNameByArity(
987 const SourceString('=='), 1); 1005 const SourceString('=='), 1);
988 Function kind = (classElement == backend.jsNullClass) 1006 Function kind = (classElement == backend.jsNullClass)
989 ? js.equals 1007 ? js.equals
990 : js.strictEquals; 1008 : js.strictEquals;
991 builder.addProperty(name, js.fun(['receiver', 'a'], 1009 builder.addProperty(name, js.fun(['receiver', 'a'],
992 js.block(js.return_(kind(js['receiver'], js['a']))))); 1010 js.block(js.return_(kind(js['receiver'], js['a'])))));
993 } 1011 }
994 } 1012 }
995 1013
996 void emitRuntimeClassesAndTests(CodeBuffer buffer) { 1014 void emitRuntimeTypeSupport(CodeBuffer buffer) {
997 RuntimeTypeInformation rti = backend.rti; 1015 RuntimeTypeInformation rti = backend.rti;
998 TypeChecks typeChecks = rti.getRequiredChecks(); 1016 TypeChecks typeChecks = rti.getRequiredChecks();
999 1017
1018 /// Classes that are not instantiated and native classes need a holder
1019 /// object for their checks, because there will be no class defined for
1020 /// them.
1000 bool needsHolder(ClassElement cls) { 1021 bool needsHolder(ClassElement cls) {
1001 return !neededClasses.contains(cls) || cls.isNative() || 1022 return !neededClasses.contains(cls) || cls.isNative() ||
1002 rti.isJsNative(cls); 1023 rti.isJsNative(cls);
1003 } 1024 }
1004 1025
1005 /** 1026 /**
1006 * Generates a holder object if it is needed. A holder is a JavaScript 1027 * Generates a holder object if it is needed. A holder is a JavaScript
1007 * object literal with a field [builtin$cls] that contains the name of the 1028 * object literal with a field [builtin$cls] that contains the name of the
1008 * class as a string (just like object constructors do). The is-checks for 1029 * class as a string (just like object constructors do). The is-checks for
1009 * the class are are added to the holder object later. 1030 * the class are are added to the holder object later.
1010 */ 1031 */
1011 void maybeGenerateHolder(ClassElement cls) { 1032 void maybeGenerateHolder(ClassElement cls) {
1012 if (!needsHolder(cls)) return; 1033 if (!needsHolder(cls)) return;
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 // substitutions for all checks and make emitSubstitution a NOP for the 1436 // substitutions for all checks and make emitSubstitution a NOP for the
1416 // rest of this function. 1437 // rest of this function.
1417 Set<ClassElement> emitted = new Set<ClassElement>(); 1438 Set<ClassElement> emitted = new Set<ClassElement>();
1418 // TODO(karlklose): move the computation of these checks to 1439 // TODO(karlklose): move the computation of these checks to
1419 // RuntimeTypeInformation. 1440 // RuntimeTypeInformation.
1420 if (compiler.world.needsRti(cls)) { 1441 if (compiler.world.needsRti(cls)) {
1421 emitSubstitution(superclass, emitNull: true); 1442 emitSubstitution(superclass, emitNull: true);
1422 emitted.add(superclass); 1443 emitted.add(superclass);
1423 } 1444 }
1424 for (DartType supertype in cls.allSupertypes) { 1445 for (DartType supertype in cls.allSupertypes) {
1446 ClassElement superclass = supertype.element;
1447 if (classesUsingTypeVariableTests.contains(superclass)) {
1448 emitSubstitution(superclass, emitNull: true);
1449 emitted.add(superclass);
1450 }
1425 for (ClassElement check in checkedClasses) { 1451 for (ClassElement check in checkedClasses) {
1426 if (supertype.element == check && !emitted.contains(check)) { 1452 if (supertype.element == check && !emitted.contains(check)) {
1427 // Generate substitution. If no substitution is necessary, emit 1453 // Generate substitution. If no substitution is necessary, emit
1428 // [:null:] to overwrite a (possibly) existing substitution from the 1454 // [:null:] to overwrite a (possibly) existing substitution from the
1429 // super classes. 1455 // super classes.
1430 emitSubstitution(check, emitNull: true); 1456 emitSubstitution(check, emitNull: true);
1431 emitted.add(check); 1457 emitted.add(check);
1432 } 1458 }
1433 } 1459 }
1434 } 1460 }
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2552 ..addAll(buildFinishIsolateConstructor()) 2578 ..addAll(buildFinishIsolateConstructor())
2553 ); 2579 );
2554 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( 2580 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration(
2555 new jsAst.VariableDeclaration('init'), fun); 2581 new jsAst.VariableDeclaration('init'), fun);
2556 buffer.add(jsAst.prettyPrint(decl, compiler).getText()); 2582 buffer.add(jsAst.prettyPrint(decl, compiler).getText());
2557 } 2583 }
2558 2584
2559 String assembleProgram() { 2585 String assembleProgram() {
2560 measure(() { 2586 measure(() {
2561 computeNeededClasses(); 2587 computeNeededClasses();
2562
2563 mainBuffer.add(GENERATED_BY); 2588 mainBuffer.add(GENERATED_BY);
2564 addComment(HOOKS_API_USAGE, mainBuffer); 2589 addComment(HOOKS_API_USAGE, mainBuffer);
2565 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); 2590 mainBuffer.add('function ${namer.isolateName}()$_{}\n');
2566 mainBuffer.add('init()$N$n'); 2591 mainBuffer.add('init()$N$n');
2567 // Shorten the code by using "$$" as temporary. 2592 // Shorten the code by using "$$" as temporary.
2568 classesCollector = r"$$"; 2593 classesCollector = r"$$";
2569 mainBuffer.add('var $classesCollector$_=$_{}$N'); 2594 mainBuffer.add('var $classesCollector$_=$_{}$N');
2570 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. 2595 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
2571 isolateProperties = namer.CURRENT_ISOLATE; 2596 isolateProperties = namer.CURRENT_ISOLATE;
2572 mainBuffer.add( 2597 mainBuffer.add(
2573 'var $isolateProperties$_=$_$isolatePropertiesName$N'); 2598 'var $isolateProperties$_=$_$isolatePropertiesName$N');
2574 emitClasses(mainBuffer); 2599 emitClasses(mainBuffer);
2575 mainBuffer.add(boundClosureBuffer); 2600 mainBuffer.add(boundClosureBuffer);
2576 // Clear the buffer, so that we can reuse it for the native classes. 2601 // Clear the buffer, so that we can reuse it for the native classes.
2577 boundClosureBuffer.clear(); 2602 boundClosureBuffer.clear();
2578 emitStaticFunctions(mainBuffer); 2603 emitStaticFunctions(mainBuffer);
2579 emitStaticFunctionGetters(mainBuffer); 2604 emitStaticFunctionGetters(mainBuffer);
2580 // We need to finish the classes before we construct compile time 2605 // We need to finish the classes before we construct compile time
2581 // constants. 2606 // constants.
2582 emitFinishClassesInvocationIfNecessary(mainBuffer); 2607 emitFinishClassesInvocationIfNecessary(mainBuffer);
2583 emitRuntimeClassesAndTests(mainBuffer); 2608 emitRuntimeTypeSupport(mainBuffer);
2584 emitCompileTimeConstants(mainBuffer); 2609 emitCompileTimeConstants(mainBuffer);
2585 // Static field initializations require the classes and compile-time 2610 // Static field initializations require the classes and compile-time
2586 // constants to be set up. 2611 // constants to be set up.
2587 emitStaticNonFinalFieldInitializations(mainBuffer); 2612 emitStaticNonFinalFieldInitializations(mainBuffer);
2588 emitOneShotInterceptors(mainBuffer); 2613 emitOneShotInterceptors(mainBuffer);
2589 emitGetInterceptorMethods(mainBuffer); 2614 emitGetInterceptorMethods(mainBuffer);
2590 emitLazilyInitializedStaticFields(mainBuffer); 2615 emitLazilyInitializedStaticFields(mainBuffer);
2591 2616
2592 isolateProperties = isolatePropertiesName; 2617 isolateProperties = isolatePropertiesName;
2593 // The following code should not use the short-hand for the 2618 // The following code should not use the short-hand for the
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
2691 """; 2716 """;
2692 const String HOOKS_API_USAGE = """ 2717 const String HOOKS_API_USAGE = """
2693 // The code supports the following hooks: 2718 // The code supports the following hooks:
2694 // dartPrint(message) - if this function is defined it is called 2719 // dartPrint(message) - if this function is defined it is called
2695 // instead of the Dart [print] method. 2720 // instead of the Dart [print] method.
2696 // dartMainRunner(main) - if this function is defined, the Dart [main] 2721 // dartMainRunner(main) - if this function is defined, the Dart [main]
2697 // method will not be invoked directly. 2722 // method will not be invoked directly.
2698 // Instead, a closure that will invoke [main] is 2723 // Instead, a closure that will invoke [main] is
2699 // passed to [dartMainRunner]. 2724 // passed to [dartMainRunner].
2700 """; 2725 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698