Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/names.dart'; | 8 import '../common/names.dart'; |
| 9 import '../compiler.dart'; | 9 import '../compiler.dart'; |
| 10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 /// Parallel structure for concreteTypes. | 70 /// Parallel structure for concreteTypes. |
| 71 // TODO(efortuna): Remove concreteTypes and/or parameterize InferrerEngine by | 71 // TODO(efortuna): Remove concreteTypes and/or parameterize InferrerEngine by |
| 72 // ir.Node or ast.Node type. Then remove this in favor of `concreteTypes`. | 72 // ir.Node or ast.Node type. Then remove this in favor of `concreteTypes`. |
| 73 final Map<ir.Node, TypeInformation> concreteKernelTypes = | 73 final Map<ir.Node, TypeInformation> concreteKernelTypes = |
| 74 new Map<ir.Node, TypeInformation>(); | 74 new Map<ir.Node, TypeInformation>(); |
| 75 final Set<ConstructorElement> generativeConstructorsExposingThis = | 75 final Set<ConstructorElement> generativeConstructorsExposingThis = |
| 76 new Set<ConstructorElement>(); | 76 new Set<ConstructorElement>(); |
| 77 | 77 |
| 78 /// Data computed internally within elements, like the type-mask of a send a | 78 /// Data computed internally within elements, like the type-mask of a send a |
| 79 /// list allocation, or a for-in loop. | 79 /// list allocation, or a for-in loop. |
| 80 final Map<Element, GlobalTypeInferenceElementData> inTreeData = | 80 final Map<MemberElement, GlobalTypeInferenceElementData> _memberData = |
| 81 new Map<Element, GlobalTypeInferenceElementData>(); | 81 new Map<MemberElement, GlobalTypeInferenceElementData>(); |
| 82 | 82 |
| 83 InferrerEngine(this.compiler, ClosedWorld closedWorld, | 83 InferrerEngine(this.compiler, ClosedWorld closedWorld, |
| 84 this.closedWorldRefiner, this.mainElement) | 84 this.closedWorldRefiner, this.mainElement) |
| 85 : this.types = new TypeSystem(closedWorld), | 85 : this.types = new TypeSystem(closedWorld), |
| 86 this.closedWorld = closedWorld; | 86 this.closedWorld = closedWorld; |
| 87 | 87 |
| 88 CommonElements get commonElements => closedWorld.commonElements; | 88 CommonElements get commonElements => closedWorld.commonElements; |
| 89 | 89 |
| 90 /// Returns `true` if [element] has an `@AssumeDynamic()` annotation. | 90 /// Returns `true` if [element] has an `@AssumeDynamic()` annotation. |
| 91 bool assumeDynamic(Element element) { | 91 bool assumeDynamic(Element element) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 103 * [selector] and [mask]. If [f] returns false, aborts the iteration. | 103 * [selector] and [mask]. If [f] returns false, aborts the iteration. |
| 104 */ | 104 */ |
| 105 void forEachElementMatching( | 105 void forEachElementMatching( |
| 106 Selector selector, TypeMask mask, bool f(Element element)) { | 106 Selector selector, TypeMask mask, bool f(Element element)) { |
| 107 Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask); | 107 Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask); |
| 108 for (MemberElement e in elements) { | 108 for (MemberElement e in elements) { |
| 109 if (!f(e.implementation)) return; | 109 if (!f(e.implementation)) return; |
| 110 } | 110 } |
| 111 } | 111 } |
| 112 | 112 |
| 113 GlobalTypeInferenceElementData dataOfLocalFunction( | |
| 114 LocalFunctionElement element) => | |
| 115 _dataOf(element); | |
| 116 | |
| 117 // TODO(johnniwinther): Make this private again. | 113 // TODO(johnniwinther): Make this private again. |
| 118 GlobalTypeInferenceElementData dataOfMember(MemberElement element) => | 114 GlobalTypeInferenceElementData dataOfMember(MemberElement element) => |
| 119 _dataOf(element); | 115 _memberData.putIfAbsent( |
| 116 element, () => new GlobalTypeInferenceElementData()); | |
| 120 | 117 |
| 121 GlobalTypeInferenceElementData _dataOf(AstElement element) => inTreeData | 118 GlobalTypeInferenceElementData lookupDataOfMember(MemberElement element) => |
|
Johnni Winther
2017/06/29 17:00:28
It turned out that we never (after type inference)
| |
| 122 .putIfAbsent(element, () => new GlobalTypeInferenceElementData()); | 119 _memberData[element]; |
| 123 | 120 |
| 124 /** | 121 /** |
| 125 * Update [sideEffects] with the side effects of [callee] being | 122 * Update [sideEffects] with the side effects of [callee] being |
| 126 * called with [selector]. | 123 * called with [selector]. |
| 127 */ | 124 */ |
| 128 void updateSideEffects( | 125 void updateSideEffects( |
| 129 SideEffects sideEffects, Selector selector, Element callee) { | 126 SideEffects sideEffects, Selector selector, Element callee) { |
| 130 if (callee.isField) { | 127 if (callee.isField) { |
| 131 if (callee.isInstanceMember) { | 128 if (callee.isInstanceMember) { |
| 132 if (selector.isSetter) { | 129 if (selector.isSetter) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 191 mappedType = types.nonNullSubtype(type.element); | 188 mappedType = types.nonNullSubtype(type.element); |
| 192 } | 189 } |
| 193 returnType = types.computeLUB(returnType, mappedType); | 190 returnType = types.computeLUB(returnType, mappedType); |
| 194 if (returnType == types.dynamicType) { | 191 if (returnType == types.dynamicType) { |
| 195 break; | 192 break; |
| 196 } | 193 } |
| 197 } | 194 } |
| 198 return returnType; | 195 return returnType; |
| 199 } | 196 } |
| 200 | 197 |
| 201 @deprecated | |
| 202 void updateSelectorInLocalFunction(LocalFunctionElement owner, Spannable node, | |
| 203 Selector selector, TypeMask mask) { | |
| 204 GlobalTypeInferenceElementData data = dataOfLocalFunction(owner); | |
| 205 _updateSelectorInTree(data, node, selector, mask); | |
| 206 } | |
| 207 | |
| 208 void updateSelectorInMember( | 198 void updateSelectorInMember( |
| 209 MemberElement owner, Spannable node, Selector selector, TypeMask mask) { | 199 MemberElement owner, Spannable node, Selector selector, TypeMask mask) { |
| 210 GlobalTypeInferenceElementData data = dataOfMember(owner); | 200 GlobalTypeInferenceElementData data = dataOfMember(owner); |
| 211 _updateSelectorInTree(data, node, selector, mask); | |
| 212 } | |
| 213 | |
| 214 void _updateSelectorInTree(GlobalTypeInferenceElementData data, | |
| 215 Spannable node, Selector selector, TypeMask mask) { | |
| 216 ast.Node astNode = node; | 201 ast.Node astNode = node; |
| 217 if (astNode.asSendSet() != null) { | 202 if (astNode.asSendSet() != null) { |
| 218 if (selector.isSetter || selector.isIndexSet) { | 203 if (selector.isSetter || selector.isIndexSet) { |
| 219 data.setTypeMask(node, mask); | 204 data.setTypeMask(node, mask); |
| 220 } else if (selector.isGetter || selector.isIndex) { | 205 } else if (selector.isGetter || selector.isIndex) { |
| 221 data.setGetterTypeMaskInComplexSendSet(node, mask); | 206 data.setGetterTypeMaskInComplexSendSet(node, mask); |
| 222 } else { | 207 } else { |
| 223 assert(selector.isOperator); | 208 assert(selector.isOperator); |
| 224 data.setOperatorTypeMaskInComplexSendSet(node, mask); | 209 data.setOperatorTypeMaskInComplexSendSet(node, mask); |
| 225 } | 210 } |
| (...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 915 * [sideEffects] will be updated to incorporate [callee]'s side | 900 * [sideEffects] will be updated to incorporate [callee]'s side |
| 916 * effects. | 901 * effects. |
| 917 * | 902 * |
| 918 * [inLoop] tells whether the call happens in a loop. | 903 * [inLoop] tells whether the call happens in a loop. |
| 919 */ | 904 */ |
| 920 @deprecated | 905 @deprecated |
| 921 TypeInformation registerCalledLocalFunction( | 906 TypeInformation registerCalledLocalFunction( |
| 922 Spannable node, | 907 Spannable node, |
| 923 Selector selector, | 908 Selector selector, |
| 924 TypeMask mask, | 909 TypeMask mask, |
| 925 Element caller, | 910 MemberElement caller, |
| 926 LocalFunctionElement callee, | 911 LocalFunctionElement callee, |
| 927 ArgumentsTypes arguments, | 912 ArgumentsTypes arguments, |
| 928 SideEffects sideEffects, | 913 SideEffects sideEffects, |
| 929 bool inLoop) { | 914 bool inLoop) { |
| 930 CallSiteTypeInformation info = new LocalFunctionCallSiteTypeInformation( | 915 CallSiteTypeInformation info = new LocalFunctionCallSiteTypeInformation( |
| 931 types.currentMember, | 916 types.currentMember, |
| 932 node, | 917 node, |
| 933 caller, | 918 caller, |
| 934 callee, | 919 callee, |
| 935 selector, | 920 selector, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 946 * | 931 * |
| 947 * [sideEffects] will be updated to incorporate [callee]'s side | 932 * [sideEffects] will be updated to incorporate [callee]'s side |
| 948 * effects. | 933 * effects. |
| 949 * | 934 * |
| 950 * [inLoop] tells whether the call happens in a loop. | 935 * [inLoop] tells whether the call happens in a loop. |
| 951 */ | 936 */ |
| 952 TypeInformation registerCalledMember( | 937 TypeInformation registerCalledMember( |
| 953 Spannable node, | 938 Spannable node, |
| 954 Selector selector, | 939 Selector selector, |
| 955 TypeMask mask, | 940 TypeMask mask, |
| 956 Element caller, | 941 MemberElement caller, |
| 957 MemberElement callee, | 942 MemberElement callee, |
| 958 ArgumentsTypes arguments, | 943 ArgumentsTypes arguments, |
| 959 SideEffects sideEffects, | 944 SideEffects sideEffects, |
| 960 bool inLoop) { | 945 bool inLoop) { |
| 961 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( | 946 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( |
| 962 types.currentMember, | 947 types.currentMember, |
| 963 node, | 948 node, |
| 964 caller, | 949 caller, |
| 965 callee, | 950 callee, |
| 966 selector, | 951 selector, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1006 * [sideEffects] will be updated to incorporate the potential | 991 * [sideEffects] will be updated to incorporate the potential |
| 1007 * callees' side effects. | 992 * callees' side effects. |
| 1008 * | 993 * |
| 1009 * [inLoop] tells whether the call happens in a loop. | 994 * [inLoop] tells whether the call happens in a loop. |
| 1010 */ | 995 */ |
| 1011 TypeInformation registerCalledSelector( | 996 TypeInformation registerCalledSelector( |
| 1012 ast.Node node, | 997 ast.Node node, |
| 1013 Selector selector, | 998 Selector selector, |
| 1014 TypeMask mask, | 999 TypeMask mask, |
| 1015 TypeInformation receiverType, | 1000 TypeInformation receiverType, |
| 1016 Element caller, | 1001 MemberElement caller, |
| 1017 ArgumentsTypes arguments, | 1002 ArgumentsTypes arguments, |
| 1018 SideEffects sideEffects, | 1003 SideEffects sideEffects, |
| 1019 bool inLoop) { | 1004 bool inLoop) { |
| 1020 if (selector.isClosureCall) { | 1005 if (selector.isClosureCall) { |
| 1021 return registerCalledClosure(node, selector, mask, receiverType, caller, | 1006 return registerCalledClosure(node, selector, mask, receiverType, caller, |
| 1022 arguments, sideEffects, inLoop); | 1007 arguments, sideEffects, inLoop); |
| 1023 } | 1008 } |
| 1024 | 1009 |
| 1025 closedWorld.locateMembers(selector, mask).forEach((_callee) { | 1010 closedWorld.locateMembers(selector, mask).forEach((_callee) { |
| 1026 MemberElement callee = _callee; | 1011 MemberElement callee = _callee; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1072 * [sideEffects] will be updated to incorporate the potential | 1057 * [sideEffects] will be updated to incorporate the potential |
| 1073 * callees' side effects. | 1058 * callees' side effects. |
| 1074 * | 1059 * |
| 1075 * [inLoop] tells whether the call happens in a loop. | 1060 * [inLoop] tells whether the call happens in a loop. |
| 1076 */ | 1061 */ |
| 1077 TypeInformation registerCalledClosure( | 1062 TypeInformation registerCalledClosure( |
| 1078 ast.Node node, | 1063 ast.Node node, |
| 1079 Selector selector, | 1064 Selector selector, |
| 1080 TypeMask mask, | 1065 TypeMask mask, |
| 1081 TypeInformation closure, | 1066 TypeInformation closure, |
| 1082 Element caller, | 1067 MemberElement caller, |
| 1083 ArgumentsTypes arguments, | 1068 ArgumentsTypes arguments, |
| 1084 SideEffects sideEffects, | 1069 SideEffects sideEffects, |
| 1085 bool inLoop) { | 1070 bool inLoop) { |
| 1086 sideEffects.setDependsOnSomething(); | 1071 sideEffects.setDependsOnSomething(); |
| 1087 sideEffects.setAllSideEffects(); | 1072 sideEffects.setAllSideEffects(); |
| 1088 CallSiteTypeInformation info = new ClosureCallSiteTypeInformation( | 1073 CallSiteTypeInformation info = new ClosureCallSiteTypeInformation( |
| 1089 types.currentMember, | 1074 types.currentMember, |
| 1090 node, | 1075 node, |
| 1091 caller, | 1076 caller, |
| 1092 selector, | 1077 selector, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1236 /** | 1221 /** |
| 1237 * Records that the captured variable [local] is read. | 1222 * Records that the captured variable [local] is read. |
| 1238 */ | 1223 */ |
| 1239 void recordCapturedLocalRead(Local local) {} | 1224 void recordCapturedLocalRead(Local local) {} |
| 1240 | 1225 |
| 1241 /** | 1226 /** |
| 1242 * Records that the variable [local] is being updated. | 1227 * Records that the variable [local] is being updated. |
| 1243 */ | 1228 */ |
| 1244 void recordLocalUpdate(Local local, TypeInformation type) {} | 1229 void recordLocalUpdate(Local local, TypeInformation type) {} |
| 1245 } | 1230 } |
| OLD | NEW |