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

Side by Side Diff: pkg/compiler/lib/src/inferrer/builder.dart

Issue 2955353002: Split inference type-info accessors into members, parameters and local functions (Closed)
Patch Set: Cleanup Created 3 years, 5 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
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 library simple_types_inferrer; 5 library simple_types_inferrer;
6 6
7 import '../closure.dart' show ClosureRepresentationInfo; 7 import '../closure.dart' show ClosureRepresentationInfo;
8 import '../common.dart'; 8 import '../common.dart';
9 import '../common/names.dart' show Identifiers, Selectors; 9 import '../common/names.dart' show Identifiers, Selectors;
10 import '../compiler.dart' show Compiler; 10 import '../compiler.dart' show Compiler;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 node = resolvedAst.node; 95 node = resolvedAst.node;
96 } 96 }
97 FieldInitializationScope fieldScope = 97 FieldInitializationScope fieldScope =
98 analyzedElement.isGenerativeConstructor 98 analyzedElement.isGenerativeConstructor
99 ? new FieldInitializationScope(types) 99 ? new FieldInitializationScope(types)
100 : null; 100 : null;
101 locals = 101 locals =
102 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope); 102 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope);
103 } 103 }
104 104
105 ElementGraphBuilder(Element element, ResolvedAst resolvedAst, 105 ElementGraphBuilder(AstElement element, ResolvedAst resolvedAst,
106 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) 106 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler])
107 : this.internal( 107 : this.internal(
108 element, 108 element,
109 resolvedAst, 109 resolvedAst,
110 element.outermostEnclosingMemberOrTopLevel.implementation, 110 element.outermostEnclosingMemberOrTopLevel.implementation,
111 inferrer, 111 inferrer,
112 compiler, 112 compiler,
113 handler); 113 handler);
114 114
115 TreeElements get elements => resolvedAst.elements; 115 TreeElements get elements => resolvedAst.elements;
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 } 884 }
885 885
886 TypeInformation visitCascade(ast.Cascade node) { 886 TypeInformation visitCascade(ast.Cascade node) {
887 // Ignore the result of the cascade send and return the type of the cascade 887 // Ignore the result of the cascade send and return the type of the cascade
888 // receiver. 888 // receiver.
889 visit(node.expression); 889 visit(node.expression);
890 return cascadeReceiverStack.removeLast(); 890 return cascadeReceiverStack.removeLast();
891 } 891 }
892 892
893 void analyzeSuperConstructorCall( 893 void analyzeSuperConstructorCall(
894 AstElement target, ArgumentsTypes arguments) { 894 ConstructorElement target, ArgumentsTypes arguments) {
895 ResolvedAst resolvedAst = target.resolvedAst; 895 ResolvedAst resolvedAst = target.resolvedAst;
896 inferrer.analyze(resolvedAst, arguments); 896 inferrer.analyze(resolvedAst, arguments);
897 isThisExposed = isThisExposed || inferrer.checkIfExposesThis(target); 897 isThisExposed = isThisExposed || inferrer.checkIfExposesThis(target);
898 } 898 }
899 899
900 TypeInformation run() { 900 TypeInformation run() {
901 var node; 901 var node;
902 if (resolvedAst.kind == ResolvedAstKind.PARSED) { 902 if (resolvedAst.kind == ResolvedAstKind.PARSED) {
903 node = resolvedAst.node; 903 node = resolvedAst.node;
904 } 904 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 // constructor comes from the corresponding parameter of the target. 937 // constructor comes from the corresponding parameter of the target.
938 938
939 // If this is a default value from a different context (because 939 // If this is a default value from a different context (because
940 // the current function is synthetic, e.g., a constructor from 940 // the current function is synthetic, e.g., a constructor from
941 // a mixin application), we have to start a new inferrer visitor 941 // a mixin application), we have to start a new inferrer visitor
942 // with the correct context. 942 // with the correct context.
943 // TODO(johnniwinther): Remove once function signatures are fixed. 943 // TODO(johnniwinther): Remove once function signatures are fixed.
944 ElementGraphBuilder visitor = this; 944 ElementGraphBuilder visitor = this;
945 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return; 945 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return;
946 if (element.functionDeclaration != analyzedElement) { 946 if (element.functionDeclaration != analyzedElement) {
947 visitor = new ElementGraphBuilder(element.functionDeclaration, 947 ConstructorElement constructor = element.functionDeclaration;
948 visitor = new ElementGraphBuilder(constructor,
948 element.functionDeclaration.resolvedAst, compiler, inferrer); 949 element.functionDeclaration.resolvedAst, compiler, inferrer);
949 } 950 }
950 TypeInformation type = 951 TypeInformation type =
951 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); 952 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue);
952 inferrer.setDefaultTypeOfParameter(element, type); 953 inferrer.setDefaultTypeOfParameter(element, type);
953 }); 954 });
954 955
955 if (inferrer.isNativeMember(analyzedElement)) { 956 if (inferrer.isNativeMember(analyzedElement)) {
956 // Native methods do not have a body, and we currently just say 957 // Native methods do not have a body, and we currently just say
957 // they return dynamic. 958 // they return dynamic.
958 return types.dynamicType; 959 return types.dynamicType;
959 } 960 }
960 961
961 if (analyzedElement.isGenerativeConstructor) { 962 if (analyzedElement.isGenerativeConstructor) {
962 isThisExposed = false; 963 isThisExposed = false;
963 signature.forEachParameter((FormalElement _element) { 964 signature.forEachParameter((FormalElement _element) {
964 ParameterElement element = _element; 965 ParameterElement element = _element;
965 TypeInformation parameterType = inferrer.typeOfElement(element); 966 TypeInformation parameterType = inferrer.typeOfParameter(element);
966 if (element.isInitializingFormal) { 967 if (element.isInitializingFormal) {
967 InitializingFormalElement initializingFormal = element; 968 InitializingFormalElement initializingFormal = element;
968 if (initializingFormal.fieldElement.isFinal) { 969 if (initializingFormal.fieldElement.isFinal) {
969 inferrer.recordTypeOfFinalField(node, analyzedElement, 970 inferrer.recordTypeOfFinalField(
970 initializingFormal.fieldElement, parameterType); 971 initializingFormal.fieldElement, parameterType);
971 } else { 972 } else {
972 locals.updateField(initializingFormal.fieldElement, parameterType); 973 locals.updateField(initializingFormal.fieldElement, parameterType);
973 inferrer.recordTypeOfNonFinalField(initializingFormal.node, 974 inferrer.recordTypeOfNonFinalField(
974 initializingFormal.fieldElement, parameterType); 975 initializingFormal.fieldElement, parameterType);
975 } 976 }
976 } 977 }
977 locals.update(element, parameterType, node); 978 locals.update(element, parameterType, node);
978 }); 979 });
979 ClassElement cls = analyzedElement.enclosingClass; 980 ClassElement cls = analyzedElement.enclosingClass;
980 Spannable spannable = node; 981 Spannable spannable = node;
981 if (analyzedElement.isSynthesized) { 982 if (analyzedElement.isSynthesized) {
982 spannable = analyzedElement; 983 spannable = analyzedElement;
983 ConstructorElement constructor = analyzedElement; 984 ConstructorElement constructor = analyzedElement;
(...skipping 15 matching lines...) Expand all
999 // For a generative constructor like: `Foo();`, we synthesize 1000 // For a generative constructor like: `Foo();`, we synthesize
1000 // a call to the default super constructor (the one that takes 1001 // a call to the default super constructor (the one that takes
1001 // no argument). Resolution ensures that such a constructor 1002 // no argument). Resolution ensures that such a constructor
1002 // exists. 1003 // exists.
1003 if (!isConstructorRedirect && 1004 if (!isConstructorRedirect &&
1004 !seenSuperConstructorCall && 1005 !seenSuperConstructorCall &&
1005 !cls.isObject) { 1006 !cls.isObject) {
1006 ConstructorElement target = cls.superclass.lookupDefaultConstructor(); 1007 ConstructorElement target = cls.superclass.lookupDefaultConstructor();
1007 ArgumentsTypes arguments = new ArgumentsTypes([], {}); 1008 ArgumentsTypes arguments = new ArgumentsTypes([], {});
1008 analyzeSuperConstructorCall(target, arguments); 1009 analyzeSuperConstructorCall(target, arguments);
1009 inferrer.registerCalledElement(node, null, null, outermostElement, 1010 inferrer.registerCalledMember(node, null, null, outermostElement,
1010 target.implementation, arguments, sideEffects, inLoop); 1011 target.implementation, arguments, sideEffects, inLoop);
1011 } 1012 }
1012 visit(node.body); 1013 visit(node.body);
1013 inferrer.recordExposesThis(analyzedElement, isThisExposed); 1014 inferrer.recordExposesThis(analyzedElement, isThisExposed);
1014 } 1015 }
1015 if (!isConstructorRedirect) { 1016 if (!isConstructorRedirect) {
1016 // Iterate over all instance fields, and give a null type to 1017 // Iterate over all instance fields, and give a null type to
1017 // fields that we haven'TypeInformation initialized for sure. 1018 // fields that we haven'TypeInformation initialized for sure.
1018 cls.forEachInstanceField((_, FieldElement field) { 1019 cls.forEachInstanceField((_, FieldElement field) {
1019 if (field.isFinal) return; 1020 if (field.isFinal) return;
1020 TypeInformation type = locals.fieldScope.readField(field); 1021 TypeInformation type = locals.fieldScope.readField(field);
1021 ResolvedAst resolvedAst = field.resolvedAst; 1022 ResolvedAst resolvedAst = field.resolvedAst;
1022 if (type == null && resolvedAst.body == null) { 1023 if (type == null && resolvedAst.body == null) {
1023 inferrer.recordTypeOfNonFinalField( 1024 inferrer.recordTypeOfNonFinalField(field, types.nullType);
1024 spannable, field, types.nullType);
1025 } 1025 }
1026 }); 1026 });
1027 } 1027 }
1028 if (analyzedElement.isGenerativeConstructor && cls.isAbstract) { 1028 if (analyzedElement.isGenerativeConstructor && cls.isAbstract) {
1029 if (closedWorld.isInstantiated(cls)) { 1029 if (closedWorld.isInstantiated(cls)) {
1030 returnType = types.nonNullSubclass(cls); 1030 returnType = types.nonNullSubclass(cls);
1031 } else { 1031 } else {
1032 // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this 1032 // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this
1033 // case; it's never called. 1033 // case; it's never called.
1034 returnType = types.nonNullEmpty(); 1034 returnType = types.nonNullEmpty();
1035 } 1035 }
1036 } else { 1036 } else {
1037 returnType = types.nonNullExact(cls); 1037 returnType = types.nonNullExact(cls);
1038 } 1038 }
1039 } else { 1039 } else {
1040 signature.forEachParameter((FormalElement _element) { 1040 signature.forEachParameter((FormalElement _element) {
1041 ParameterElement element = _element; 1041 ParameterElement element = _element;
1042 locals.update(element, inferrer.typeOfElement(element), node); 1042 locals.update(element, inferrer.typeOfParameter(element), node);
1043 }); 1043 });
1044 visit(node.body); 1044 visit(node.body);
1045 switch (function.asyncMarker) { 1045 switch (function.asyncMarker) {
1046 case AsyncMarker.SYNC: 1046 case AsyncMarker.SYNC:
1047 if (returnType == null) { 1047 if (returnType == null) {
1048 // No return in the body. 1048 // No return in the body.
1049 returnType = locals.seenReturnOrThrow 1049 returnType = locals.seenReturnOrThrow
1050 ? types.nonNullEmpty() // Body always throws. 1050 ? types.nonNullEmpty() // Body always throws.
1051 : types.nullType; 1051 : types.nullType;
1052 } else if (!locals.seenReturnOrThrow) { 1052 } else if (!locals.seenReturnOrThrow) {
1053 // We haven'TypeInformation seen returns on all branches. So the met hod may 1053 // We haven'TypeInformation seen returns on all branches. So the met hod may
1054 // also return null. 1054 // also return null.
1055 returnType = inferrer.addReturnTypeFor( 1055 if (analyzedElement.isLocal) {
Siggi Cherem (dart-lang) 2017/06/28 16:30:24 to avoid duplicating this if-else in these four ca
Johnni Winther 2017/06/29 12:36:48 Done.
1056 analyzedElement, returnType, types.nullType); 1056 returnType = inferrer.addReturnTypeForLocalFunction(
1057 analyzedElement, returnType, types.nullType);
1058 } else {
1059 returnType = inferrer.addReturnTypeForMethod(
1060 analyzedElement, returnType, types.nullType);
1061 }
1057 } 1062 }
1058 break; 1063 break;
1059 1064
1060 case AsyncMarker.SYNC_STAR: 1065 case AsyncMarker.SYNC_STAR:
1061 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type 1066 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type
1062 // contained is the method body's return type. 1067 // contained is the method body's return type.
1063 returnType = inferrer.addReturnTypeFor( 1068 if (analyzedElement.isLocal) {
1064 analyzedElement, returnType, types.syncStarIterableType); 1069 returnType = inferrer.addReturnTypeForLocalFunction(
1070 analyzedElement, returnType, types.syncStarIterableType);
1071 } else {
1072 returnType = inferrer.addReturnTypeForMethod(
1073 analyzedElement, returnType, types.syncStarIterableType);
1074 }
1065 break; 1075 break;
1066 1076
1067 case AsyncMarker.ASYNC: 1077 case AsyncMarker.ASYNC:
1068 returnType = inferrer.addReturnTypeFor( 1078 if (analyzedElement.isLocal) {
1069 analyzedElement, returnType, types.asyncFutureType); 1079 returnType = inferrer.addReturnTypeForLocalFunction(
1080 analyzedElement, returnType, types.asyncFutureType);
1081 } else {
1082 returnType = inferrer.addReturnTypeForMethod(
1083 analyzedElement, returnType, types.asyncFutureType);
1084 }
1070 break; 1085 break;
1071 1086
1072 case AsyncMarker.ASYNC_STAR: 1087 case AsyncMarker.ASYNC_STAR:
1073 returnType = inferrer.addReturnTypeFor( 1088 if (analyzedElement.isLocal) {
1074 analyzedElement, returnType, types.asyncStarStreamType); 1089 returnType = inferrer.addReturnTypeForLocalFunction(
1090 analyzedElement, returnType, types.asyncStarStreamType);
1091 } else {
1092 returnType = inferrer.addReturnTypeForMethod(
1093 analyzedElement, returnType, types.asyncStarStreamType);
1094 }
1075 break; 1095 break;
1076 } 1096 }
1077 } 1097 }
1078 1098
1079 inferrer.closedWorldRefiner 1099 inferrer.closedWorldRefiner
1080 .registerSideEffects(analyzedElement.declaration, sideEffects); 1100 .registerSideEffects(analyzedElement.declaration, sideEffects);
1081 assert(breaksFor.isEmpty); 1101 assert(breaksFor.isEmpty);
1082 assert(continuesFor.isEmpty); 1102 assert(continuesFor.isEmpty);
1083 return returnType; 1103 return returnType;
1084 } 1104 }
1085 1105
1086 TypeInformation visitFunctionExpression(ast.FunctionExpression node) { 1106 TypeInformation visitFunctionExpression(ast.FunctionExpression node) {
1087 // We loose track of [this] in closures (see issue 20840). To be on 1107 // We loose track of [this] in closures (see issue 20840). To be on
1088 // the safe side, we mark [this] as exposed here. We could do better by 1108 // the safe side, we mark [this] as exposed here. We could do better by
1089 // analyzing the closure. 1109 // analyzing the closure.
1090 // TODO(herhut): Analyze whether closure exposes this. 1110 // TODO(herhut): Analyze whether closure exposes this.
1091 isThisExposed = true; 1111 isThisExposed = true;
1092 LocalFunctionElement element = elements.getFunctionDefinition(node); 1112 LocalFunctionElement element = elements.getFunctionDefinition(node);
1093 // We don'TypeInformation put the closure in the work queue of the 1113 // We don'TypeInformation put the closure in the work queue of the
1094 // inferrer, because it will share information with its enclosing 1114 // inferrer, because it will share information with its enclosing
1095 // method, like for example the types of local variables. 1115 // method, like for example the types of local variables.
1096 LocalsHandler closureLocals = 1116 LocalsHandler closureLocals =
1097 new LocalsHandler.from(locals, node, useOtherTryBlock: false); 1117 new LocalsHandler.from(locals, node, useOtherTryBlock: false);
1098 ElementGraphBuilder visitor = new ElementGraphBuilder( 1118 ElementGraphBuilder visitor = new ElementGraphBuilder(
1099 element, element.resolvedAst, compiler, inferrer, closureLocals); 1119 element, element.resolvedAst, compiler, inferrer, closureLocals);
1100 visitor.run(); 1120 visitor.run();
1101 inferrer.recordReturnType(element, visitor.returnType); 1121 inferrer.recordReturnTypeOfLocalFunction(element, visitor.returnType);
1102 1122
1103 // Record the types of captured non-boxed variables. Types of 1123 // Record the types of captured non-boxed variables. Types of
1104 // these variables may already be there, because of an analysis of 1124 // these variables may already be there, because of an analysis of
1105 // a previous closure. 1125 // a previous closure.
1106 ClosureRepresentationInfo nestedClosureData = compiler 1126 ClosureRepresentationInfo nestedClosureData = compiler
1107 .backendStrategy.closureDataLookup 1127 .backendStrategy.closureDataLookup
1108 .getClosureRepresentationInfo(element); 1128 .getClosureRepresentationInfo(element);
1109 nestedClosureData.forEachCapturedVariable((variable, field) { 1129 nestedClosureData.forEachCapturedVariable((variable, field) {
1110 if (!nestedClosureData.isVariableBoxed(variable)) { 1130 if (!nestedClosureData.isVariableBoxed(variable)) {
1111 if (variable == nestedClosureData.thisLocal) { 1131 if (variable == nestedClosureData.thisLocal) {
1112 inferrer.recordType(field, thisType); 1132 inferrer.recordTypeOfField(field, thisType);
1113 } 1133 }
1114 // The type is null for type parameters. 1134 // The type is null for type parameters.
1115 if (locals.locals[variable] == null) return; 1135 if (locals.locals[variable] == null) return;
1116 inferrer.recordType(field, locals.locals[variable]); 1136 inferrer.recordTypeOfField(field, locals.locals[variable]);
1117 } 1137 }
1118 capturedVariables.add(variable); 1138 capturedVariables.add(variable);
1119 }); 1139 });
1120 1140
1121 return inferrer.concreteTypes.putIfAbsent(node, () { 1141 return inferrer.concreteTypes.putIfAbsent(node, () {
1122 return types.allocateClosure(node, element); 1142 return types.allocateClosure(node, element);
1123 }); 1143 });
1124 } 1144 }
1125 1145
1126 TypeInformation visitFunctionDeclaration(ast.FunctionDeclaration node) { 1146 TypeInformation visitFunctionDeclaration(ast.FunctionDeclaration node) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1203 if (element.isField) { 1223 if (element.isField) {
1204 ResolvedAst elementResolvedAst = element.resolvedAst; 1224 ResolvedAst elementResolvedAst = element.resolvedAst;
1205 if (!selector.isSetter && 1225 if (!selector.isSetter &&
1206 isInClassOrSubclass(element) && 1226 isInClassOrSubclass(element) &&
1207 !element.isFinal && 1227 !element.isFinal &&
1208 locals.fieldScope.readField(element) == null && 1228 locals.fieldScope.readField(element) == null &&
1209 elementResolvedAst.body == null) { 1229 elementResolvedAst.body == null) {
1210 // If the field is being used before this constructor 1230 // If the field is being used before this constructor
1211 // actually had a chance to initialize it, say it can be 1231 // actually had a chance to initialize it, say it can be
1212 // null. 1232 // null.
1213 inferrer.recordTypeOfNonFinalField( 1233 inferrer.recordTypeOfNonFinalField(element, types.nullType);
1214 resolvedAst.node, element, types.nullType);
1215 } 1234 }
1216 // Accessing a field does not expose [:this:]. 1235 // Accessing a field does not expose [:this:].
1217 return true; 1236 return true;
1218 } 1237 }
1219 // TODO(ngeoffray): We could do better here if we knew what we 1238 // TODO(ngeoffray): We could do better here if we knew what we
1220 // are calling does not expose this. 1239 // are calling does not expose this.
1221 isThisExposed = true; 1240 isThisExposed = true;
1222 return false; 1241 return false;
1223 }); 1242 });
1224 } 1243 }
(...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 MemberElement single = targets.first; 2008 MemberElement single = targets.first;
1990 if (single.isField) { 2009 if (single.isField) {
1991 locals.updateField(single, rhsType); 2010 locals.updateField(single, rhsType);
1992 } 2011 }
1993 } 2012 }
1994 } 2013 }
1995 handleDynamicSend( 2014 handleDynamicSend(
1996 node, setterSelector, setterMask, receiverType, arguments); 2015 node, setterSelector, setterMask, receiverType, arguments);
1997 } else if (element.isField) { 2016 } else if (element.isField) {
1998 if (element.isFinal) { 2017 if (element.isFinal) {
1999 inferrer.recordTypeOfFinalField( 2018 inferrer.recordTypeOfFinalField(element, rhsType);
2000 node, outermostElement, element, rhsType);
2001 } else { 2019 } else {
2002 if (analyzedElement.isGenerativeConstructor) { 2020 if (analyzedElement.isGenerativeConstructor) {
2003 locals.updateField(element, rhsType); 2021 locals.updateField(element, rhsType);
2004 } 2022 }
2005 if (visitingInitializers) { 2023 if (visitingInitializers) {
2006 inferrer.recordTypeOfNonFinalField(node, element, rhsType); 2024 inferrer.recordTypeOfNonFinalField(element, rhsType);
2007 } else { 2025 } else {
2008 handleDynamicSend( 2026 handleDynamicSend(
2009 node, setterSelector, setterMask, receiverType, arguments); 2027 node, setterSelector, setterMask, receiverType, arguments);
2010 } 2028 }
2011 } 2029 }
2012 } else if (element.isLocal) { 2030 } else if (element.isLocal) {
2013 locals.update(element, rhsType, node); 2031 locals.update(element, rhsType, node);
2014 } 2032 }
2015 return rhsType; 2033 return rhsType;
2016 } 2034 }
(...skipping 20 matching lines...) Expand all
2037 if (!Selectors.noSuchMethod_.signatureApplies(element)) { 2055 if (!Selectors.noSuchMethod_.signatureApplies(element)) {
2038 ClassElement objectClass = closedWorld.commonElements.objectClass; 2056 ClassElement objectClass = closedWorld.commonElements.objectClass;
2039 element = objectClass.lookupMember(Identifiers.noSuchMethod_); 2057 element = objectClass.lookupMember(Identifiers.noSuchMethod_);
2040 } 2058 }
2041 return handleStaticSend(node, selector, mask, element, arguments); 2059 return handleStaticSend(node, selector, mask, element, arguments);
2042 } 2060 }
2043 2061
2044 /// Handle a .call invocation on the values retrieved from the super 2062 /// Handle a .call invocation on the values retrieved from the super
2045 /// [element]. For instance `super.foo(bar)` where `foo` is a field or getter. 2063 /// [element]. For instance `super.foo(bar)` where `foo` is a field or getter.
2046 TypeInformation handleSuperClosureCall( 2064 TypeInformation handleSuperClosureCall(
2047 ast.Send node, Element element, ast.NodeList arguments) { 2065 ast.Send node, MemberElement element, ast.NodeList arguments) {
2048 ArgumentsTypes argumentTypes = analyzeArguments(arguments.nodes); 2066 ArgumentsTypes argumentTypes = analyzeArguments(arguments.nodes);
2049 Selector selector = elements.getSelector(node); 2067 Selector selector = elements.getSelector(node);
2050 TypeMask mask = inTreeData.typeOfSend(node); 2068 TypeMask mask = inTreeData.typeOfSend(node);
2051 // TODO(herhut): We could do better here if we knew what we 2069 // TODO(herhut): We could do better here if we knew what we
2052 // are calling does not expose this. 2070 // are calling does not expose this.
2053 isThisExposed = true; 2071 isThisExposed = true;
2054 return inferrer.registerCalledClosure( 2072 return inferrer.registerCalledClosure(
2055 node, 2073 node,
2056 selector, 2074 selector,
2057 mask, 2075 mask,
2058 inferrer.typeOfElement(element), 2076 inferrer.typeOfMember(element),
2059 outermostElement, 2077 outermostElement,
2060 argumentTypes, 2078 argumentTypes,
2061 sideEffects, 2079 sideEffects,
2062 inLoop); 2080 inLoop);
2063 } 2081 }
2064 2082
2065 /// Handle an invocation of super [method]. 2083 /// Handle an invocation of super [method].
2066 TypeInformation handleSuperMethodInvoke( 2084 TypeInformation handleSuperMethodInvoke(
2067 ast.Send node, MethodElement method, ArgumentsTypes arguments) { 2085 ast.Send node, MethodElement method, ArgumentsTypes arguments) {
2068 // TODO(herhut): We could do better here if we knew what we 2086 // TODO(herhut): We could do better here if we knew what we
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
2347 ? types.nullType 2365 ? types.nullType
2348 : arguments.positional[1]; 2366 : arguments.positional[1];
2349 2367
2350 return inferrer.concreteTypes.putIfAbsent( 2368 return inferrer.concreteTypes.putIfAbsent(
2351 node, 2369 node,
2352 () => types.allocateList(types.fixedListType, node, outermostElement, 2370 () => types.allocateList(types.fixedListType, node, outermostElement,
2353 elementType, length)); 2371 elementType, length));
2354 } else if (Elements.isConstructorOfTypedArraySubclass( 2372 } else if (Elements.isConstructorOfTypedArraySubclass(
2355 constructor, closedWorld)) { 2373 constructor, closedWorld)) {
2356 int length = findLength(node); 2374 int length = findLength(node);
2357 TypeInformation elementType = inferrer 2375 TypeInformation elementType =
2358 .returnTypeOfElement(target.enclosingClass.lookupMember('[]')); 2376 inferrer.returnTypeOfMember(target.enclosingClass.lookupMember('[]'));
2359 return inferrer.concreteTypes.putIfAbsent( 2377 return inferrer.concreteTypes.putIfAbsent(
2360 node, 2378 node,
2361 () => types.allocateList(types.nonNullExact(target.enclosingClass), 2379 () => types.allocateList(types.nonNullExact(target.enclosingClass),
2362 node, outermostElement, elementType, length)); 2380 node, outermostElement, elementType, length));
2363 } else { 2381 } else {
2364 return returnType; 2382 return returnType;
2365 } 2383 }
2366 } 2384 }
2367 2385
2368 @override 2386 @override
2369 TypeInformation bulkHandleNew(ast.NewExpression node, _) { 2387 TypeInformation bulkHandleNew(ast.NewExpression node, _) {
2370 Element element = elements[node.send]; 2388 Element element = elements[node.send];
2371 return handleConstructorSend(node.send, element); 2389 return handleConstructorSend(node.send, element);
2372 } 2390 }
2373 2391
2374 @override 2392 @override
2375 TypeInformation errorNonConstantConstructorInvoke( 2393 TypeInformation errorNonConstantConstructorInvoke(
2376 ast.NewExpression node, 2394 ast.NewExpression node,
2377 Element element, 2395 Element element,
2378 ResolutionDartType type, 2396 ResolutionDartType type,
2379 ast.NodeList arguments, 2397 ast.NodeList arguments,
2380 CallStructure callStructure, 2398 CallStructure callStructure,
2381 _) { 2399 _) {
2382 return bulkHandleNew(node, _); 2400 return bulkHandleNew(node, _);
2383 } 2401 }
2384 2402
2385 /// Handle invocation of a top level or static field or getter [element]. 2403 /// Handle invocation of a top level or static field or getter [element].
2386 TypeInformation handleStaticFieldOrGetterInvoke( 2404 TypeInformation handleStaticFieldOrGetterInvoke(
2387 ast.Send node, Element element) { 2405 ast.Send node, MemberElement element) {
2388 ArgumentsTypes arguments = analyzeArguments(node.arguments); 2406 ArgumentsTypes arguments = analyzeArguments(node.arguments);
2389 Selector selector = elements.getSelector(node); 2407 Selector selector = elements.getSelector(node);
2390 TypeMask mask = inTreeData.typeOfSend(node); 2408 TypeMask mask = inTreeData.typeOfSend(node);
2391 handleStaticSend(node, selector, mask, element, arguments); 2409 handleStaticSend(node, selector, mask, element, arguments);
2392 return inferrer.registerCalledClosure( 2410 return inferrer.registerCalledClosure(
2393 node, 2411 node,
2394 selector, 2412 selector,
2395 mask, 2413 mask,
2396 inferrer.typeOfElement(element), 2414 inferrer.typeOfMember(element),
2397 outermostElement, 2415 outermostElement,
2398 arguments, 2416 arguments,
2399 sideEffects, 2417 sideEffects,
2400 inLoop); 2418 inLoop);
2401 } 2419 }
2402 2420
2403 /// Handle invocation of a top level or static [function]. 2421 /// Handle invocation of a top level or static [function].
2404 TypeInformation handleStaticFunctionInvoke( 2422 TypeInformation handleStaticFunctionInvoke(
2405 ast.Send node, MethodElement function) { 2423 ast.Send node, MethodElement function) {
2406 if (compiler.backend.isForeign(closedWorld.commonElements, function)) { 2424 if (compiler.backend.isForeign(closedWorld.commonElements, function)) {
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
2699 LocalFunctionElement function, 2717 LocalFunctionElement function,
2700 ast.NodeList arguments, 2718 ast.NodeList arguments,
2701 CallStructure callStructure, 2719 CallStructure callStructure,
2702 _) { 2720 _) {
2703 ArgumentsTypes argumentTypes = analyzeArguments(node.arguments); 2721 ArgumentsTypes argumentTypes = analyzeArguments(node.arguments);
2704 Selector selector = elements.getSelector(node); 2722 Selector selector = elements.getSelector(node);
2705 TypeMask mask = inTreeData.typeOfSend(node); 2723 TypeMask mask = inTreeData.typeOfSend(node);
2706 // This only works for function statements. We need a 2724 // This only works for function statements. We need a
2707 // more sophisticated type system with function types to support 2725 // more sophisticated type system with function types to support
2708 // more. 2726 // more.
2709 return inferrer.registerCalledElement(node, selector, mask, 2727 return inferrer.registerCalledLocalFunction(node, selector, mask,
2710 outermostElement, function, argumentTypes, sideEffects, inLoop); 2728 outermostElement, function, argumentTypes, sideEffects, inLoop);
2711 } 2729 }
2712 2730
2713 @override 2731 @override
2714 TypeInformation visitLocalFunctionIncompatibleInvoke( 2732 TypeInformation visitLocalFunctionIncompatibleInvoke(
2715 ast.Send node, 2733 ast.Send node,
2716 LocalFunctionElement function, 2734 LocalFunctionElement function,
2717 ast.NodeList arguments, 2735 ast.NodeList arguments,
2718 CallStructure callStructure, 2736 CallStructure callStructure,
2719 _) { 2737 _) {
2720 analyzeArguments(node.arguments); 2738 analyzeArguments(node.arguments);
2721 return types.dynamicType; 2739 return types.dynamicType;
2722 } 2740 }
2723 2741
2724 TypeInformation handleStaticSend(ast.Node node, Selector selector, 2742 TypeInformation handleStaticSend(ast.Node node, Selector selector,
2725 TypeMask mask, Element element, ArgumentsTypes arguments) { 2743 TypeMask mask, MemberElement element, ArgumentsTypes arguments) {
2726 assert(!element.isFactoryConstructor || 2744 assert(!element.isFactoryConstructor ||
2727 !(element as ConstructorElement).isRedirectingFactory); 2745 !(element as ConstructorElement).isRedirectingFactory);
2728 // Erroneous elements may be unresolved, for example missing getters. 2746 // Erroneous elements may be unresolved, for example missing getters.
2729 if (Elements.isUnresolved(element)) return types.dynamicType; 2747 if (Elements.isUnresolved(element)) return types.dynamicType;
2730 // TODO(herhut): should we follow redirecting constructors here? We would 2748 // TODO(herhut): should we follow redirecting constructors here? We would
2731 // need to pay attention if the constructor is pointing to an erroneous 2749 // need to pay attention if the constructor is pointing to an erroneous
2732 // element. 2750 // element.
2733 return inferrer.registerCalledElement(node, selector, mask, 2751 return inferrer.registerCalledMember(node, selector, mask, outermostElement,
2734 outermostElement, element, arguments, sideEffects, inLoop); 2752 element, arguments, sideEffects, inLoop);
2735 } 2753 }
2736 2754
2737 TypeInformation handleDynamicSend(ast.Node node, Selector selector, 2755 TypeInformation handleDynamicSend(ast.Node node, Selector selector,
2738 TypeMask mask, TypeInformation receiverType, ArgumentsTypes arguments) { 2756 TypeMask mask, TypeInformation receiverType, ArgumentsTypes arguments) {
2739 assert(receiverType != null); 2757 assert(receiverType != null);
2740 if (types.selectorNeedsUpdate(receiverType, mask)) { 2758 if (types.selectorNeedsUpdate(receiverType, mask)) {
2741 mask = receiverType == types.dynamicType 2759 mask = receiverType == types.dynamicType
2742 ? null 2760 ? null
2743 : types.newTypedSelector(receiverType, mask); 2761 : types.newTypedSelector(receiverType, mask);
2744 inferrer.updateSelectorInTree(analyzedElement, node, selector, mask); 2762 inferrer.updateSelectorInTree(analyzedElement, node, selector, mask);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2801 return types.boolType; 2819 return types.boolType;
2802 } else if (types.isNull(arguments.positional[0])) { 2820 } else if (types.isNull(arguments.positional[0])) {
2803 potentiallyAddNullCheck(node, node.receiver); 2821 potentiallyAddNullCheck(node, node.receiver);
2804 return types.boolType; 2822 return types.boolType;
2805 } 2823 }
2806 } 2824 }
2807 return handleDynamicSend(node, selector, mask, receiverType, arguments); 2825 return handleDynamicSend(node, selector, mask, receiverType, arguments);
2808 } 2826 }
2809 2827
2810 void recordReturnType(TypeInformation type) { 2828 void recordReturnType(TypeInformation type) {
2811 returnType = inferrer.addReturnTypeFor(analyzedElement, returnType, type); 2829 if (analyzedElement.isLocal) {
2830 returnType = inferrer.addReturnTypeForLocalFunction(
2831 analyzedElement, returnType, type);
2832 } else {
2833 returnType =
2834 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type);
2835 }
2812 } 2836 }
2813 2837
2814 TypeInformation synthesizeForwardingCall( 2838 TypeInformation synthesizeForwardingCall(
2815 Spannable node, ConstructorElement element) { 2839 Spannable node, ConstructorElement element) {
2816 element = element.implementation; 2840 element = element.implementation;
2817 FunctionElement function = analyzedElement; 2841 FunctionElement function = analyzedElement;
2818 FunctionSignature signature = function.functionSignature; 2842 FunctionSignature signature = function.functionSignature;
2819 FunctionSignature calleeSignature = element.functionSignature; 2843 FunctionSignature calleeSignature = element.functionSignature;
2820 if (!calleeSignature.isCompatibleWith(signature)) { 2844 if (!calleeSignature.isCompatibleWith(signature)) {
2821 return types.nonNullEmpty(); 2845 return types.nonNullEmpty();
(...skipping 14 matching lines...) Expand all
2836 named[element.name] = locals.use(element); 2860 named[element.name] = locals.use(element);
2837 }); 2861 });
2838 } else { 2862 } else {
2839 signature.forEachOptionalParameter((FormalElement _element) { 2863 signature.forEachOptionalParameter((FormalElement _element) {
2840 ParameterElement element = _element; 2864 ParameterElement element = _element;
2841 unnamed.add(locals.use(element)); 2865 unnamed.add(locals.use(element));
2842 }); 2866 });
2843 } 2867 }
2844 2868
2845 ArgumentsTypes arguments = new ArgumentsTypes(unnamed, named); 2869 ArgumentsTypes arguments = new ArgumentsTypes(unnamed, named);
2846 return inferrer.registerCalledElement(node, null, null, outermostElement, 2870 return inferrer.registerCalledMember(node, null, null, outermostElement,
2847 element, arguments, sideEffects, inLoop); 2871 element, arguments, sideEffects, inLoop);
2848 } 2872 }
2849 2873
2850 TypeInformation visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { 2874 TypeInformation visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) {
2851 ConstructorElement element = elements.getRedirectingTargetConstructor(node); 2875 ConstructorElement element = elements.getRedirectingTargetConstructor(node);
2852 if (Elements.isMalformed(element)) { 2876 if (Elements.isMalformed(element)) {
2853 recordReturnType(types.dynamicType); 2877 recordReturnType(types.dynamicType);
2854 } else { 2878 } else {
2855 // We don'TypeInformation create a selector for redirecting factories, and 2879 // We don'TypeInformation create a selector for redirecting factories, and
2856 // the send is just a property access. Therefore we must 2880 // the send is just a property access. Therefore we must
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2938 Selector moveNextSelector = Selectors.moveNext; 2962 Selector moveNextSelector = Selectors.moveNext;
2939 TypeMask moveNextMask = inTreeData.typeOfIteratorMoveNext(node); 2963 TypeMask moveNextMask = inTreeData.typeOfIteratorMoveNext(node);
2940 2964
2941 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, 2965 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector,
2942 iteratorMask, expressionType, new ArgumentsTypes.empty()); 2966 iteratorMask, expressionType, new ArgumentsTypes.empty());
2943 2967
2944 return handleForInLoop(node, iteratorType, currentSelector, currentMask, 2968 return handleForInLoop(node, iteratorType, currentSelector, currentMask,
2945 moveNextSelector, moveNextMask); 2969 moveNextSelector, moveNextMask);
2946 } 2970 }
2947 } 2971 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698