OLD | NEW |
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 type_graph_inferrer; | 5 part of type_graph_inferrer; |
6 | 6 |
7 /** | 7 /** |
8 * Common class for all nodes in the graph. The current nodes are: | 8 * Common class for all nodes in the graph. The current nodes are: |
9 * | 9 * |
10 * - Concrete types | 10 * - Concrete types |
(...skipping 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 | 1052 |
1053 // The set of [TypeInformation] where values from the traced map could | 1053 // The set of [TypeInformation] where values from the traced map could |
1054 // flow in. | 1054 // flow in. |
1055 final Setlet<TypeInformation> flowsInto = new Setlet<TypeInformation>(); | 1055 final Setlet<TypeInformation> flowsInto = new Setlet<TypeInformation>(); |
1056 | 1056 |
1057 // Set to false once analysis has succeeded. | 1057 // Set to false once analysis has succeeded. |
1058 bool bailedOut = true; | 1058 bool bailedOut = true; |
1059 bool analyzed = false; | 1059 bool analyzed = false; |
1060 | 1060 |
1061 // Set to false if a statically unknown key flows into this map. | 1061 // Set to false if a statically unknown key flows into this map. |
1062 bool isDictionary = true; | 1062 bool _allKeysAreStrings = true; |
| 1063 |
| 1064 bool get inDictionaryMode => !bailedOut && _allKeysAreStrings; |
1063 | 1065 |
1064 MapTypeInformation(this.initialType, this.keyType, this.valueType) { | 1066 MapTypeInformation(this.initialType, this.keyType, this.valueType) { |
1065 keyType.addUser(this); | 1067 keyType.addUser(this); |
1066 valueType.addUser(this); | 1068 valueType.addUser(this); |
1067 type = initialType; | 1069 type = initialType; |
1068 } | 1070 } |
1069 | 1071 |
1070 TypeInformation addEntryAssignment(TypeInformation key, | 1072 TypeInformation addEntryAssignment(TypeInformation key, |
1071 TypeInformation value, | 1073 TypeInformation value, |
1072 [bool nonNull = false]) { | 1074 [bool nonNull = false]) { |
1073 TypeInformation newInfo = null; | 1075 TypeInformation newInfo = null; |
1074 if (isDictionary && key is StringLiteralTypeInformation) { | 1076 if (_allKeysAreStrings && key is StringLiteralTypeInformation) { |
1075 String keyString = key.asString(); | 1077 String keyString = key.asString(); |
1076 typeInfoMap.putIfAbsent(keyString, | 1078 typeInfoMap.putIfAbsent(keyString, |
1077 () => newInfo = new ValueInMapTypeInformation(null, nonNull)); | 1079 () => newInfo = new ValueInMapTypeInformation(null, nonNull)); |
1078 typeInfoMap[keyString].addAssignment(value); | 1080 typeInfoMap[keyString].addAssignment(value); |
1079 } else { | 1081 } else { |
1080 isDictionary = false; | 1082 _allKeysAreStrings = false; |
1081 typeInfoMap.clear(); | 1083 typeInfoMap.clear(); |
1082 } | 1084 } |
1083 keyType.addAssignment(key); | 1085 keyType.addAssignment(key); |
1084 valueType.addAssignment(value); | 1086 valueType.addAssignment(value); |
1085 if (newInfo != null) newInfo.addUser(this); | 1087 if (newInfo != null) newInfo.addUser(this); |
1086 | 1088 |
1087 return newInfo; | 1089 return newInfo; |
1088 } | 1090 } |
1089 | 1091 |
1090 List<TypeInformation> addMapAssignment(MapTypeInformation map) { | 1092 List<TypeInformation> addMapAssignment(MapTypeInformation other) { |
1091 List<TypeInformation> newInfos = <TypeInformation>[]; | 1093 List<TypeInformation> newInfos = <TypeInformation>[]; |
1092 if (map.isDictionary) { | 1094 if (_allKeysAreStrings && other.inDictionaryMode) { |
1093 map.typeInfoMap.forEach((keyString, value) { | 1095 other.typeInfoMap.forEach((keyString, value) { |
1094 typeInfoMap.putIfAbsent(keyString, () { | 1096 typeInfoMap.putIfAbsent(keyString, () { |
1095 TypeInformation newInfo = new ValueInMapTypeInformation(null, false); | 1097 TypeInformation newInfo = new ValueInMapTypeInformation(null, false); |
1096 newInfos.add(newInfo); | 1098 newInfos.add(newInfo); |
1097 return newInfo; | 1099 return newInfo; |
1098 }); | 1100 }); |
1099 typeInfoMap[keyString].addAssignment(value); | 1101 typeInfoMap[keyString].addAssignment(value); |
1100 }); | 1102 }); |
| 1103 } else { |
| 1104 _allKeysAreStrings = false; |
| 1105 typeInfoMap.clear(); |
1101 } | 1106 } |
1102 keyType.addAssignment(map.keyType); | 1107 keyType.addAssignment(other.keyType); |
1103 valueType.addAssignment(map.valueType); | 1108 valueType.addAssignment(other.valueType); |
1104 | 1109 |
1105 return newInfos; | 1110 return newInfos; |
1106 } | 1111 } |
1107 | 1112 |
1108 markAsInferred() { | 1113 markAsInferred() { |
1109 keyType.inferred = valueType.inferred = true; | 1114 keyType.inferred = valueType.inferred = true; |
1110 typeInfoMap.values.forEach((v) => v.inferred = true); | 1115 typeInfoMap.values.forEach((v) => v.inferred = true); |
1111 } | 1116 } |
1112 | 1117 |
1113 addAssignment(TypeInformation other) { | 1118 addAssignment(TypeInformation other) { |
1114 throw "not supported"; | 1119 throw "not supported"; |
1115 } | 1120 } |
1116 | 1121 |
1117 accept(TypeInformationVisitor visitor) { | 1122 accept(TypeInformationVisitor visitor) { |
1118 return visitor.visitMapTypeInformation(this); | 1123 return visitor.visitMapTypeInformation(this); |
1119 } | 1124 } |
1120 | 1125 |
1121 TypeMask toTypeMask(TypeGraphInferrerEngine inferrer) { | 1126 TypeMask toTypeMask(TypeGraphInferrerEngine inferrer) { |
1122 if (isDictionary) { | 1127 if (inDictionaryMode) { |
1123 Map<String, TypeMask> mappings = new Map<String, TypeMask>(); | 1128 Map<String, TypeMask> mappings = new Map<String, TypeMask>(); |
1124 for (var key in typeInfoMap.keys) { | 1129 for (var key in typeInfoMap.keys) { |
1125 mappings[key] = typeInfoMap[key].type; | 1130 mappings[key] = typeInfoMap[key].type; |
1126 } | 1131 } |
1127 return new DictionaryTypeMask(initialType.forwardTo, | 1132 return new DictionaryTypeMask(initialType.forwardTo, |
1128 initialType.allocationNode, | 1133 initialType.allocationNode, |
1129 initialType.allocationElement, | 1134 initialType.allocationElement, |
1130 keyType.type, | 1135 keyType.type, |
1131 valueType.type, | 1136 valueType.type, |
1132 mappings); | 1137 mappings); |
1133 } else { | 1138 } else { |
1134 return new MapTypeMask(initialType.forwardTo, | 1139 return new MapTypeMask(initialType.forwardTo, |
1135 initialType.allocationNode, | 1140 initialType.allocationNode, |
1136 initialType.allocationElement, | 1141 initialType.allocationElement, |
1137 keyType.type, | 1142 keyType.type, |
1138 valueType.type); | 1143 valueType.type); |
1139 } | 1144 } |
1140 } | 1145 } |
1141 | 1146 |
1142 TypeMask refine(TypeGraphInferrerEngine inferrer) { | 1147 TypeMask refine(TypeGraphInferrerEngine inferrer) { |
1143 if (!bailedOut && type.isDictionary != isDictionary) { | 1148 if (type.isDictionary != inDictionaryMode) { |
1144 return toTypeMask(inferrer); | 1149 return toTypeMask(inferrer); |
1145 } else if (!bailedOut && type.isDictionary) { | 1150 } else if (type.isDictionary) { |
| 1151 assert(inDictionaryMode); |
1146 DictionaryTypeMask mask = type; | 1152 DictionaryTypeMask mask = type; |
1147 for (var key in typeInfoMap.keys) { | 1153 for (var key in typeInfoMap.keys) { |
1148 TypeInformation value = typeInfoMap[key]; | 1154 TypeInformation value = typeInfoMap[key]; |
1149 if (!mask.typeMap.containsKey(key) && | 1155 if (!mask.typeMap.containsKey(key) && |
1150 !value.type.containsAll(inferrer.compiler) && | 1156 !value.type.containsAll(inferrer.compiler) && |
1151 !value.type.isNullable) { | 1157 !value.type.isNullable) { |
1152 return toTypeMask(inferrer); | 1158 return toTypeMask(inferrer); |
1153 } | 1159 } |
1154 if (mask.typeMap[key] != typeInfoMap[key].type) { | 1160 if (mask.typeMap[key] != typeInfoMap[key].type) { |
1155 return toTypeMask(inferrer); | 1161 return toTypeMask(inferrer); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1274 T visitListTypeInformation(ListTypeInformation info); | 1280 T visitListTypeInformation(ListTypeInformation info); |
1275 T visitMapTypeInformation(MapTypeInformation info); | 1281 T visitMapTypeInformation(MapTypeInformation info); |
1276 T visitConcreteTypeInformation(ConcreteTypeInformation info); | 1282 T visitConcreteTypeInformation(ConcreteTypeInformation info); |
1277 T visitStringLiteralTypeInformation(StringLiteralTypeInformation info); | 1283 T visitStringLiteralTypeInformation(StringLiteralTypeInformation info); |
1278 T visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info); | 1284 T visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info); |
1279 T visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info); | 1285 T visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info); |
1280 T visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info); | 1286 T visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info); |
1281 T visitElementTypeInformation(ElementTypeInformation info); | 1287 T visitElementTypeInformation(ElementTypeInformation info); |
1282 T visitClosureTypeInformation(ClosureTypeInformation info); | 1288 T visitClosureTypeInformation(ClosureTypeInformation info); |
1283 } | 1289 } |
OLD | NEW |