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

Side by Side Diff: pkg/compiler/lib/src/js_backend/runtime_types.dart

Issue 2812393003: dart2js: Capture typedef arguments once (Closed)
Patch Set: comment Created 3 years, 8 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
« no previous file with comments | « no previous file | pkg/js_ast/lib/src/nodes.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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.backend; 5 part of js_backend.backend;
6 6
7 /// For each class, stores the possible class subtype tests that could succeed. 7 /// For each class, stores the possible class subtype tests that could succeed.
8 abstract class TypeChecks { 8 abstract class TypeChecks {
9 /// Get the set of checks required for class [element]. 9 /// Get the set of checks required for class [element].
10 Iterable<TypeCheck> operator [](ClassElement element); 10 Iterable<TypeCheck> operator [](ClassElement element);
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after
871 return '$name<$arguments>'; 871 return '$name<$arguments>';
872 } 872 }
873 } 873 }
874 874
875 class TypeRepresentationGenerator implements DartTypeVisitor { 875 class TypeRepresentationGenerator implements DartTypeVisitor {
876 final Namer namer; 876 final Namer namer;
877 final CodeEmitterTask emitter; 877 final CodeEmitterTask emitter;
878 OnVariableCallback onVariable; 878 OnVariableCallback onVariable;
879 ShouldEncodeTypedefCallback shouldEncodeTypedef; 879 ShouldEncodeTypedefCallback shouldEncodeTypedef;
880 880
881 Map<ResolutionTypeVariableType, jsAst.Expression> typedefBindings;
882
881 TypeRepresentationGenerator(this.namer, this.emitter); 883 TypeRepresentationGenerator(this.namer, this.emitter);
882 884
883 /** 885 /**
884 * Creates a type representation for [type]. [onVariable] is called to provide 886 * Creates a type representation for [type]. [onVariable] is called to provide
885 * the type representation for type variables. 887 * the type representation for type variables.
886 */ 888 */
887 jsAst.Expression getTypeRepresentation( 889 jsAst.Expression getTypeRepresentation(
888 ResolutionDartType type, 890 ResolutionDartType type,
889 OnVariableCallback onVariable, 891 OnVariableCallback onVariable,
890 ShouldEncodeTypedefCallback encodeTypedef) { 892 ShouldEncodeTypedefCallback encodeTypedef) {
893 assert(typedefBindings == null);
891 this.onVariable = onVariable; 894 this.onVariable = onVariable;
892 this.shouldEncodeTypedef = (encodeTypedef != null) 895 this.shouldEncodeTypedef = (encodeTypedef != null)
893 ? encodeTypedef 896 ? encodeTypedef
894 : (ResolutionTypedefType type) => false; 897 : (ResolutionTypedefType type) => false;
895 jsAst.Expression representation = visit(type); 898 jsAst.Expression representation = visit(type);
896 this.onVariable = null; 899 this.onVariable = null;
897 this.shouldEncodeTypedef = null; 900 this.shouldEncodeTypedef = null;
898 return representation; 901 return representation;
899 } 902 }
900 903
901 jsAst.Expression getJavaScriptClassName(Element element) { 904 jsAst.Expression getJavaScriptClassName(Element element) {
902 return emitter.typeAccess(element); 905 return emitter.typeAccess(element);
903 } 906 }
904 907
905 @override 908 @override
906 visit(ResolutionDartType type, [_]) => type.accept(this, null); 909 visit(ResolutionDartType type, [_]) => type.accept(this, null);
907 910
908 visitTypeVariableType(ResolutionTypeVariableType type, _) { 911 visitTypeVariableType(ResolutionTypeVariableType type, _) {
912 if (typedefBindings != null) {
913 assert(typedefBindings[type] != null);
914 return typedefBindings[type];
915 }
909 return onVariable(type); 916 return onVariable(type);
910 } 917 }
911 918
912 visitDynamicType(ResolutionDynamicType type, _) { 919 visitDynamicType(ResolutionDynamicType type, _) {
913 return js('null'); 920 return js('null');
914 } 921 }
915 922
916 visitInterfaceType(ResolutionInterfaceType type, _) { 923 visitInterfaceType(ResolutionInterfaceType type, _) {
917 jsAst.Expression name = getJavaScriptClassName(type.element); 924 jsAst.Expression name = getJavaScriptClassName(type.element);
918 return type.treatAsRaw ? name : visitList(type.typeArguments, head: name); 925 return type.treatAsRaw ? name : visitList(type.typeArguments, head: name);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 } 1001 }
995 1002
996 visitVoidType(ResolutionVoidType type, _) { 1003 visitVoidType(ResolutionVoidType type, _) {
997 // TODO(ahe): Reify void type ("null" means "dynamic"). 1004 // TODO(ahe): Reify void type ("null" means "dynamic").
998 return js('null'); 1005 return js('null');
999 } 1006 }
1000 1007
1001 visitTypedefType(ResolutionTypedefType type, _) { 1008 visitTypedefType(ResolutionTypedefType type, _) {
1002 bool shouldEncode = shouldEncodeTypedef(type); 1009 bool shouldEncode = shouldEncodeTypedef(type);
1003 ResolutionDartType unaliasedType = type.unaliased; 1010 ResolutionDartType unaliasedType = type.unaliased;
1011
1012 var oldBindings = typedefBindings;
1013 if (typedefBindings == null) {
1014 // First level typedef - capture arguments for re-use within typedef body.
1015 //
1016 // The type `Map<T, Foo<Set<T>>>` contains one type variable referenced
1017 // twice, so there are two inputs into the HTypeInfoExpression
1018 // instruction.
1019 //
1020 // If Foo is a typedef, T can be reused, e.g.
1021 //
1022 // typedef E Foo<E>(E a, E b);
1023 //
1024 // As the typedef is expanded (to (Set<T>, Set<T>) => Set<T>) it should
1025 // not consume additional types from the to-level input. We prevent this
1026 // by capturing the types and using the captured type expressions inside
1027 // the typedef expansion.
1028 //
1029 // TODO(sra): We should make the type subexpression Foo<...> be a second
1030 // HTypeInfoExpression, with Set<T> as its input (a third
1031 // HTypeInfoExpression). This would share all the Set<T> subexpressions
1032 // instead of duplicating them. This would require HTypeInfoExpression
1033 // inputs to correspond to type variables AND typedefs.
1034 typedefBindings = <ResolutionTypeVariableType, jsAst.Expression>{};
1035 type.forEachTypeVariable((variable) {
1036 if (variable is! MethodTypeVariableType) {
1037 typedefBindings[variable] = onVariable(variable);
1038 }
1039 });
1040 }
1041
1042 jsAst.Expression finish(jsAst.Expression result) {
1043 typedefBindings = oldBindings;
1044 return result;
1045 }
1046
1004 if (shouldEncode) { 1047 if (shouldEncode) {
1005 jsAst.ObjectInitializer initializer = unaliasedType.accept(this, null); 1048 jsAst.ObjectInitializer initializer = unaliasedType.accept(this, null);
1006 // We have to encode the aliased type. 1049 // We have to encode the aliased type.
1007 jsAst.Expression name = getJavaScriptClassName(type.element); 1050 jsAst.Expression name = getJavaScriptClassName(type.element);
1008 jsAst.Expression encodedTypedef = 1051 jsAst.Expression encodedTypedef =
1009 type.treatAsRaw ? name : visitList(type.typeArguments, head: name); 1052 type.treatAsRaw ? name : visitList(type.typeArguments, head: name);
1010 1053
1011 // Add it to the function-type object. 1054 // Add it to the function-type object.
1012 jsAst.LiteralString tag = js.string(namer.typedefTag); 1055 jsAst.LiteralString tag = js.string(namer.typedefTag);
1013 initializer.properties.add(new jsAst.Property(tag, encodedTypedef)); 1056 initializer.properties.add(new jsAst.Property(tag, encodedTypedef));
1014 return initializer; 1057 return finish(initializer);
1015 } else { 1058 } else {
1016 return unaliasedType.accept(this, null); 1059 return finish(unaliasedType.accept(this, null));
1017 } 1060 }
1018 } 1061 }
1019 } 1062 }
1020 1063
1021 class TypeCheckMapping implements TypeChecks { 1064 class TypeCheckMapping implements TypeChecks {
1022 final Map<ClassElement, Set<TypeCheck>> map = 1065 final Map<ClassElement, Set<TypeCheck>> map =
1023 new Map<ClassElement, Set<TypeCheck>>(); 1066 new Map<ClassElement, Set<TypeCheck>>();
1024 1067
1025 Iterable<TypeCheck> operator [](ClassElement element) { 1068 Iterable<TypeCheck> operator [](ClassElement element) {
1026 Set<TypeCheck> result = map[element]; 1069 Set<TypeCheck> result = map[element];
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 * substition for this check. 1177 * substition for this check.
1135 */ 1178 */
1136 class TypeCheck { 1179 class TypeCheck {
1137 final ClassElement cls; 1180 final ClassElement cls;
1138 final Substitution substitution; 1181 final Substitution substitution;
1139 final int hashCode = _nextHash = (_nextHash + 100003).toUnsigned(30); 1182 final int hashCode = _nextHash = (_nextHash + 100003).toUnsigned(30);
1140 static int _nextHash = 0; 1183 static int _nextHash = 0;
1141 1184
1142 TypeCheck(this.cls, this.substitution); 1185 TypeCheck(this.cls, this.substitution);
1143 } 1186 }
OLDNEW
« no previous file with comments | « no previous file | pkg/js_ast/lib/src/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698