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

Side by Side Diff: lib/compiler/implementation/ssa/types.dart

Issue 11341041: Fix for dartbug.com/6036: the intersection of two different types is not always conflicting. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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 ssa; 5 part of ssa;
6 6
7 abstract class HType { 7 abstract class HType {
8 const HType(); 8 const HType();
9 9
10 /** 10 /**
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 * * INTEGER.intersect(NUMBER) => INTEGER. 102 * * INTEGER.intersect(NUMBER) => INTEGER.
103 * * DOUBLE.intersect(INTEGER) => CONFLICTING. 103 * * DOUBLE.intersect(INTEGER) => CONFLICTING.
104 * * MUTABLE_ARRAY.intersect(READABLE_ARRAY) => MUTABLE_ARRAY. 104 * * MUTABLE_ARRAY.intersect(READABLE_ARRAY) => MUTABLE_ARRAY.
105 * 105 *
106 * When there is no predefined type to represent the intersection returns 106 * When there is no predefined type to represent the intersection returns
107 * [CONFLICTING]. 107 * [CONFLICTING].
108 * 108 *
109 * An intersection with [UNKNOWN] returns the non-UNKNOWN type. An 109 * An intersection with [UNKNOWN] returns the non-UNKNOWN type. An
110 * intersection with [CONFLICTING] returns [CONFLICTING]. 110 * intersection with [CONFLICTING] returns [CONFLICTING].
111 */ 111 */
112 abstract HType intersection(HType other); 112 abstract HType intersection(HType other, Compiler compiler);
113 113
114 /** 114 /**
115 * The union of two types is the union of its values. For example: 115 * The union of two types is the union of its values. For example:
116 * * INTEGER.union(NUMBER) => NUMBER. 116 * * INTEGER.union(NUMBER) => NUMBER.
117 * * DOUBLE.union(INTEGER) => NUMBER. 117 * * DOUBLE.union(INTEGER) => NUMBER.
118 * * MUTABLE_ARRAY.union(READABLE_ARRAY) => READABLE_ARRAY. 118 * * MUTABLE_ARRAY.union(READABLE_ARRAY) => READABLE_ARRAY.
119 * 119 *
120 * When there is no predefined type to represent the union returns 120 * When there is no predefined type to represent the union returns
121 * [UNKNOWN]. 121 * [UNKNOWN].
122 * 122 *
123 * A union with [UNKNOWN] returns [UNKNOWN]. 123 * A union with [UNKNOWN] returns [UNKNOWN].
124 * A union of [CONFLICTING] with any other types returns the other type. 124 * A union of [CONFLICTING] with any other types returns the other type.
125 */ 125 */
126 abstract HType union(HType other); 126 abstract HType union(HType other, Compiler compiler);
127 } 127 }
128 128
129 /** Used to represent [HType.UNKNOWN] and [HType.CONFLICTING]. */ 129 /** Used to represent [HType.UNKNOWN] and [HType.CONFLICTING]. */
130 abstract class HAnalysisType extends HType { 130 abstract class HAnalysisType extends HType {
131 final String name; 131 final String name;
132 const HAnalysisType(this.name); 132 const HAnalysisType(this.name);
133 String toString() => name; 133 String toString() => name;
134 134
135 DartType computeType(Compiler compiler) => null; 135 DartType computeType(Compiler compiler) => null;
136 } 136 }
137 137
138 class HUnknownType extends HAnalysisType { 138 class HUnknownType extends HAnalysisType {
139 const HUnknownType() : super("unknown"); 139 const HUnknownType() : super("unknown");
140 bool canBePrimitive() => true; 140 bool canBePrimitive() => true;
141 bool canBeNull() => true; 141 bool canBeNull() => true;
142 142
143 HType union(HType other) => this; 143 HType union(HType other, Compiler compiler) => this;
144 HType intersection(HType other) => other; 144 HType intersection(HType other, Compiler compiler) => other;
145 } 145 }
146 146
147 class HConflictingType extends HAnalysisType { 147 class HConflictingType extends HAnalysisType {
148 const HConflictingType() : super("conflicting"); 148 const HConflictingType() : super("conflicting");
149 bool canBePrimitive() => true; 149 bool canBePrimitive() => true;
150 bool canBeNull() => true; 150 bool canBeNull() => true;
151 151
152 HType union(HType other) => other; 152 HType union(HType other, Compiler compiler) => other;
153 HType intersection(HType other) => this; 153 HType intersection(HType other, Compiler compiler) => this;
154 } 154 }
155 155
156 abstract class HPrimitiveType extends HType { 156 abstract class HPrimitiveType extends HType {
157 const HPrimitiveType(); 157 const HPrimitiveType();
158 bool isPrimitive() => true; 158 bool isPrimitive() => true;
159 bool canBePrimitive() => true; 159 bool canBePrimitive() => true;
160 bool isPrimitiveOrNull() => true; 160 bool isPrimitiveOrNull() => true;
161 } 161 }
162 162
163 class HNullType extends HPrimitiveType { 163 class HNullType extends HPrimitiveType {
164 const HNullType(); 164 const HNullType();
165 bool canBeNull() => true; 165 bool canBeNull() => true;
166 bool isNull() => true; 166 bool isNull() => true;
167 String toString() => 'null'; 167 String toString() => 'null';
168 168
169 DartType computeType(Compiler compiler) => null; 169 DartType computeType(Compiler compiler) => null;
170 170
171 HType union(HType other) { 171 HType union(HType other, Compiler compiler) {
172 if (other.isConflicting()) return HType.NULL; 172 if (other.isConflicting()) return HType.NULL;
173 if (other.isUnknown()) return HType.UNKNOWN; 173 if (other.isUnknown()) return HType.UNKNOWN;
174 if (other.isString()) return HType.STRING_OR_NULL; 174 if (other.isString()) return HType.STRING_OR_NULL;
175 if (other.isInteger()) return HType.INTEGER_OR_NULL; 175 if (other.isInteger()) return HType.INTEGER_OR_NULL;
176 if (other.isDouble()) return HType.DOUBLE_OR_NULL; 176 if (other.isDouble()) return HType.DOUBLE_OR_NULL;
177 if (other.isNumber()) return HType.NUMBER_OR_NULL; 177 if (other.isNumber()) return HType.NUMBER_OR_NULL;
178 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL; 178 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL;
179 if (!other.canBeNull()) return HType.UNKNOWN; 179 if (!other.canBeNull()) return HType.UNKNOWN;
180 return other; 180 return other;
181 } 181 }
182 182
183 HType intersection(HType other) { 183 HType intersection(HType other, Compiler compiler) {
184 if (other.isUnknown()) return HType.NULL; 184 if (other.isUnknown()) return HType.NULL;
185 if (other.isConflicting()) return HType.CONFLICTING; 185 if (other.isConflicting()) return HType.CONFLICTING;
186 if (!other.canBeNull()) return HType.CONFLICTING; 186 if (!other.canBeNull()) return HType.CONFLICTING;
187 return HType.NULL; 187 return HType.NULL;
188 } 188 }
189 } 189 }
190 190
191 abstract class HPrimitiveOrNullType extends HType { 191 abstract class HPrimitiveOrNullType extends HType {
192 const HPrimitiveOrNullType(); 192 const HPrimitiveOrNullType();
193 bool canBePrimitive() => true; 193 bool canBePrimitive() => true;
194 bool canBeNull() => true; 194 bool canBeNull() => true;
195 bool isPrimitiveOrNull() => true; 195 bool isPrimitiveOrNull() => true;
196 } 196 }
197 197
198 class HBooleanOrNullType extends HPrimitiveOrNullType { 198 class HBooleanOrNullType extends HPrimitiveOrNullType {
199 const HBooleanOrNullType(); 199 const HBooleanOrNullType();
200 String toString() => "boolean or null"; 200 String toString() => "boolean or null";
201 bool isBooleanOrNull() => true; 201 bool isBooleanOrNull() => true;
202 202
203 DartType computeType(Compiler compiler) { 203 DartType computeType(Compiler compiler) {
204 return compiler.boolClass.computeType(compiler); 204 return compiler.boolClass.computeType(compiler);
205 } 205 }
206 206
207 HType union(HType other) { 207 HType union(HType other, Compiler compiler) {
208 if (other.isConflicting()) return HType.BOOLEAN_OR_NULL; 208 if (other.isConflicting()) return HType.BOOLEAN_OR_NULL;
209 if (other.isUnknown()) return HType.UNKNOWN; 209 if (other.isUnknown()) return HType.UNKNOWN;
210 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; 210 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL;
211 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL; 211 if (other.isBoolean()) return HType.BOOLEAN_OR_NULL;
212 if (other.isNull()) return HType.BOOLEAN_OR_NULL; 212 if (other.isNull()) return HType.BOOLEAN_OR_NULL;
213 return HType.UNKNOWN; 213 return HType.UNKNOWN;
214 } 214 }
215 215
216 HType intersection(HType other) { 216 HType intersection(HType other, Compiler compiler) {
217 if (other.isConflicting()) return HType.CONFLICTING; 217 if (other.isConflicting()) return HType.CONFLICTING;
218 if (other.isUnknown()) return HType.BOOLEAN_OR_NULL; 218 if (other.isUnknown()) return HType.BOOLEAN_OR_NULL;
219 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; 219 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL;
220 if (other.isBoolean()) return HType.BOOLEAN; 220 if (other.isBoolean()) return HType.BOOLEAN;
221 if (other.canBeNull()) return HType.NULL; 221 if (other.canBeNull()) return HType.NULL;
222 return HType.CONFLICTING; 222 return HType.CONFLICTING;
223 } 223 }
224 } 224 }
225 225
226 class HBooleanType extends HPrimitiveType { 226 class HBooleanType extends HPrimitiveType {
227 const HBooleanType(); 227 const HBooleanType();
228 bool isBoolean() => true; 228 bool isBoolean() => true;
229 String toString() => "boolean"; 229 String toString() => "boolean";
230 230
231 DartType computeType(Compiler compiler) { 231 DartType computeType(Compiler compiler) {
232 return compiler.boolClass.computeType(compiler); 232 return compiler.boolClass.computeType(compiler);
233 } 233 }
234 234
235 HType union(HType other) { 235 HType union(HType other, Compiler compiler) {
236 if (other.isConflicting()) return HType.BOOLEAN; 236 if (other.isConflicting()) return HType.BOOLEAN;
237 if (other.isUnknown()) return HType.UNKNOWN; 237 if (other.isUnknown()) return HType.UNKNOWN;
238 if (other.isBoolean()) return HType.BOOLEAN; 238 if (other.isBoolean()) return HType.BOOLEAN;
239 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL; 239 if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL;
240 if (other.isNull()) return HType.BOOLEAN_OR_NULL; 240 if (other.isNull()) return HType.BOOLEAN_OR_NULL;
241 return HType.UNKNOWN; 241 return HType.UNKNOWN;
242 } 242 }
243 243
244 HType intersection(HType other) { 244 HType intersection(HType other, Compiler compiler) {
245 if (other.isConflicting()) return HType.CONFLICTING; 245 if (other.isConflicting()) return HType.CONFLICTING;
246 if (other.isUnknown()) return HType.BOOLEAN; 246 if (other.isUnknown()) return HType.BOOLEAN;
247 if (other.isBooleanOrNull()) return HType.BOOLEAN; 247 if (other.isBooleanOrNull()) return HType.BOOLEAN;
248 if (other.isBoolean()) return HType.BOOLEAN; 248 if (other.isBoolean()) return HType.BOOLEAN;
249 return HType.CONFLICTING; 249 return HType.CONFLICTING;
250 } 250 }
251 } 251 }
252 252
253 class HNumberOrNullType extends HPrimitiveOrNullType { 253 class HNumberOrNullType extends HPrimitiveOrNullType {
254 const HNumberOrNullType(); 254 const HNumberOrNullType();
255 bool isNumberOrNull() => true; 255 bool isNumberOrNull() => true;
256 String toString() => "number or null"; 256 String toString() => "number or null";
257 257
258 DartType computeType(Compiler compiler) { 258 DartType computeType(Compiler compiler) {
259 return compiler.numClass.computeType(compiler); 259 return compiler.numClass.computeType(compiler);
260 } 260 }
261 261
262 HType union(HType other) { 262 HType union(HType other, Compiler compiler) {
263 if (other.isConflicting()) return HType.NUMBER_OR_NULL; 263 if (other.isConflicting()) return HType.NUMBER_OR_NULL;
264 if (other.isUnknown()) return HType.UNKNOWN; 264 if (other.isUnknown()) return HType.UNKNOWN;
265 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; 265 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
266 if (other.isNumber()) return HType.NUMBER_OR_NULL; 266 if (other.isNumber()) return HType.NUMBER_OR_NULL;
267 if (other.isNull()) return HType.NUMBER_OR_NULL; 267 if (other.isNull()) return HType.NUMBER_OR_NULL;
268 return HType.UNKNOWN; 268 return HType.UNKNOWN;
269 } 269 }
270 270
271 HType intersection(HType other) { 271 HType intersection(HType other, Compiler compiler) {
272 if (other.isConflicting()) return HType.CONFLICTING; 272 if (other.isConflicting()) return HType.CONFLICTING;
273 if (other.isUnknown()) return HType.NUMBER_OR_NULL; 273 if (other.isUnknown()) return HType.NUMBER_OR_NULL;
274 if (other.isInteger()) return HType.INTEGER; 274 if (other.isInteger()) return HType.INTEGER;
275 if (other.isDouble()) return HType.DOUBLE; 275 if (other.isDouble()) return HType.DOUBLE;
276 if (other.isNumber()) return HType.NUMBER; 276 if (other.isNumber()) return HType.NUMBER;
277 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; 277 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL;
278 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; 278 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
279 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; 279 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
280 if (other.canBeNull()) return HType.NULL; 280 if (other.canBeNull()) return HType.NULL;
281 return HType.CONFLICTING; 281 return HType.CONFLICTING;
282 } 282 }
283 } 283 }
284 284
285 class HNumberType extends HPrimitiveType { 285 class HNumberType extends HPrimitiveType {
286 const HNumberType(); 286 const HNumberType();
287 bool isNumber() => true; 287 bool isNumber() => true;
288 String toString() => "number"; 288 String toString() => "number";
289 289
290 DartType computeType(Compiler compiler) { 290 DartType computeType(Compiler compiler) {
291 return compiler.numClass.computeType(compiler); 291 return compiler.numClass.computeType(compiler);
292 } 292 }
293 293
294 HType union(HType other) { 294 HType union(HType other, Compiler compiler) {
295 if (other.isConflicting()) return HType.NUMBER; 295 if (other.isConflicting()) return HType.NUMBER;
296 if (other.isUnknown()) return HType.UNKNOWN; 296 if (other.isUnknown()) return HType.UNKNOWN;
297 if (other.isNumber()) return HType.NUMBER; 297 if (other.isNumber()) return HType.NUMBER;
298 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; 298 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
299 if (other.isNull()) return HType.NUMBER_OR_NULL; 299 if (other.isNull()) return HType.NUMBER_OR_NULL;
300 return HType.UNKNOWN; 300 return HType.UNKNOWN;
301 } 301 }
302 302
303 HType intersection(HType other) { 303 HType intersection(HType other, Compiler compiler) {
304 if (other.isConflicting()) return HType.CONFLICTING; 304 if (other.isConflicting()) return HType.CONFLICTING;
305 if (other.isUnknown()) return HType.NUMBER; 305 if (other.isUnknown()) return HType.NUMBER;
306 if (other.isNumber()) return other; 306 if (other.isNumber()) return other;
307 if (other.isIntegerOrNull()) return HType.INTEGER; 307 if (other.isIntegerOrNull()) return HType.INTEGER;
308 if (other.isDoubleOrNull()) return HType.DOUBLE; 308 if (other.isDoubleOrNull()) return HType.DOUBLE;
309 if (other.isNumberOrNull()) return HType.NUMBER; 309 if (other.isNumberOrNull()) return HType.NUMBER;
310 return HType.CONFLICTING; 310 return HType.CONFLICTING;
311 } 311 }
312 } 312 }
313 313
314 class HIntegerOrNullType extends HNumberOrNullType { 314 class HIntegerOrNullType extends HNumberOrNullType {
315 const HIntegerOrNullType(); 315 const HIntegerOrNullType();
316 bool isIntegerOrNull() => true; 316 bool isIntegerOrNull() => true;
317 String toString() => "integer or null"; 317 String toString() => "integer or null";
318 318
319 DartType computeType(Compiler compiler) { 319 DartType computeType(Compiler compiler) {
320 return compiler.intClass.computeType(compiler); 320 return compiler.intClass.computeType(compiler);
321 } 321 }
322 322
323 HType union(HType other) { 323 HType union(HType other, Compiler compiler) {
324 if (other.isConflicting()) return HType.INTEGER_OR_NULL; 324 if (other.isConflicting()) return HType.INTEGER_OR_NULL;
325 if (other.isUnknown()) return HType.UNKNOWN; 325 if (other.isUnknown()) return HType.UNKNOWN;
326 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; 326 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL;
327 if (other.isInteger()) return HType.INTEGER_OR_NULL; 327 if (other.isInteger()) return HType.INTEGER_OR_NULL;
328 if (other.isNumber()) return HType.NUMBER_OR_NULL; 328 if (other.isNumber()) return HType.NUMBER_OR_NULL;
329 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; 329 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
330 if (other.isNull()) return HType.INTEGER_OR_NULL; 330 if (other.isNull()) return HType.INTEGER_OR_NULL;
331 return HType.UNKNOWN; 331 return HType.UNKNOWN;
332 } 332 }
333 333
334 HType intersection(HType other) { 334 HType intersection(HType other, Compiler compiler) {
335 if (other.isConflicting()) return HType.CONFLICTING; 335 if (other.isConflicting()) return HType.CONFLICTING;
336 if (other.isUnknown()) return HType.INTEGER_OR_NULL; 336 if (other.isUnknown()) return HType.INTEGER_OR_NULL;
337 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; 337 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL;
338 if (other.isInteger()) return HType.INTEGER; 338 if (other.isInteger()) return HType.INTEGER;
339 if (other.isDouble()) return HType.CONFLICTING; 339 if (other.isDouble()) return HType.CONFLICTING;
340 if (other.isDoubleOrNull()) return HType.NULL; 340 if (other.isDoubleOrNull()) return HType.NULL;
341 if (other.isNumber()) return HType.INTEGER; 341 if (other.isNumber()) return HType.INTEGER;
342 if (other.isNumberOrNull()) return HType.INTEGER_OR_NULL; 342 if (other.isNumberOrNull()) return HType.INTEGER_OR_NULL;
343 if (other.canBeNull()) return HType.NULL; 343 if (other.canBeNull()) return HType.NULL;
344 return HType.CONFLICTING; 344 return HType.CONFLICTING;
345 } 345 }
346 } 346 }
347 347
348 class HIntegerType extends HNumberType { 348 class HIntegerType extends HNumberType {
349 const HIntegerType(); 349 const HIntegerType();
350 bool isInteger() => true; 350 bool isInteger() => true;
351 String toString() => "integer"; 351 String toString() => "integer";
352 352
353 DartType computeType(Compiler compiler) { 353 DartType computeType(Compiler compiler) {
354 return compiler.intClass.computeType(compiler); 354 return compiler.intClass.computeType(compiler);
355 } 355 }
356 356
357 HType union(HType other) { 357 HType union(HType other, Compiler compiler) {
358 if (other.isConflicting()) return HType.INTEGER; 358 if (other.isConflicting()) return HType.INTEGER;
359 if (other.isUnknown()) return HType.UNKNOWN; 359 if (other.isUnknown()) return HType.UNKNOWN;
360 if (other.isInteger()) return HType.INTEGER; 360 if (other.isInteger()) return HType.INTEGER;
361 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL; 361 if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL;
362 if (other.isNumber()) return HType.NUMBER; 362 if (other.isNumber()) return HType.NUMBER;
363 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; 363 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
364 if (other.isNull()) return HType.INTEGER_OR_NULL; 364 if (other.isNull()) return HType.INTEGER_OR_NULL;
365 return HType.UNKNOWN; 365 return HType.UNKNOWN;
366 } 366 }
367 367
368 HType intersection(HType other) { 368 HType intersection(HType other, Compiler compiler) {
369 if (other.isConflicting()) return HType.CONFLICTING; 369 if (other.isConflicting()) return HType.CONFLICTING;
370 if (other.isUnknown()) return HType.INTEGER; 370 if (other.isUnknown()) return HType.INTEGER;
371 if (other.isIntegerOrNull()) return HType.INTEGER; 371 if (other.isIntegerOrNull()) return HType.INTEGER;
372 if (other.isInteger()) return HType.INTEGER; 372 if (other.isInteger()) return HType.INTEGER;
373 if (other.isDouble()) return HType.CONFLICTING; 373 if (other.isDouble()) return HType.CONFLICTING;
374 if (other.isDoubleOrNull()) return HType.CONFLICTING; 374 if (other.isDoubleOrNull()) return HType.CONFLICTING;
375 if (other.isNumber()) return HType.INTEGER; 375 if (other.isNumber()) return HType.INTEGER;
376 if (other.isNumberOrNull()) return HType.INTEGER; 376 if (other.isNumberOrNull()) return HType.INTEGER;
377 return HType.CONFLICTING; 377 return HType.CONFLICTING;
378 } 378 }
379 } 379 }
380 380
381 class HDoubleOrNullType extends HNumberOrNullType { 381 class HDoubleOrNullType extends HNumberOrNullType {
382 const HDoubleOrNullType(); 382 const HDoubleOrNullType();
383 bool isDoubleOrNull() => true; 383 bool isDoubleOrNull() => true;
384 String toString() => "double or null"; 384 String toString() => "double or null";
385 385
386 DartType computeType(Compiler compiler) { 386 DartType computeType(Compiler compiler) {
387 return compiler.doubleClass.computeType(compiler); 387 return compiler.doubleClass.computeType(compiler);
388 } 388 }
389 389
390 HType union(HType other) { 390 HType union(HType other, Compiler compiler) {
391 if (other.isConflicting()) return HType.DOUBLE_OR_NULL; 391 if (other.isConflicting()) return HType.DOUBLE_OR_NULL;
392 if (other.isUnknown()) return HType.UNKNOWN; 392 if (other.isUnknown()) return HType.UNKNOWN;
393 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; 393 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
394 if (other.isDouble()) return HType.DOUBLE_OR_NULL; 394 if (other.isDouble()) return HType.DOUBLE_OR_NULL;
395 if (other.isNumber()) return HType.NUMBER_OR_NULL; 395 if (other.isNumber()) return HType.NUMBER_OR_NULL;
396 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; 396 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
397 if (other.isNull()) return HType.DOUBLE_OR_NULL; 397 if (other.isNull()) return HType.DOUBLE_OR_NULL;
398 return HType.UNKNOWN; 398 return HType.UNKNOWN;
399 } 399 }
400 400
401 HType intersection(HType other) { 401 HType intersection(HType other, Compiler compiler) {
402 if (other.isConflicting()) return HType.CONFLICTING; 402 if (other.isConflicting()) return HType.CONFLICTING;
403 if (other.isUnknown()) return HType.DOUBLE_OR_NULL; 403 if (other.isUnknown()) return HType.DOUBLE_OR_NULL;
404 if (other.isIntegerOrNull()) return HType.NULL; 404 if (other.isIntegerOrNull()) return HType.NULL;
405 if (other.isInteger()) return HType.CONFLICTING; 405 if (other.isInteger()) return HType.CONFLICTING;
406 if (other.isDouble()) return HType.DOUBLE; 406 if (other.isDouble()) return HType.DOUBLE;
407 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; 407 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
408 if (other.isNumber()) return HType.DOUBLE; 408 if (other.isNumber()) return HType.DOUBLE;
409 if (other.isNumberOrNull()) return HType.DOUBLE_OR_NULL; 409 if (other.isNumberOrNull()) return HType.DOUBLE_OR_NULL;
410 if (other.canBeNull()) return HType.NULL; 410 if (other.canBeNull()) return HType.NULL;
411 return HType.CONFLICTING; 411 return HType.CONFLICTING;
412 } 412 }
413 } 413 }
414 414
415 class HDoubleType extends HNumberType { 415 class HDoubleType extends HNumberType {
416 const HDoubleType(); 416 const HDoubleType();
417 bool isDouble() => true; 417 bool isDouble() => true;
418 String toString() => "double"; 418 String toString() => "double";
419 419
420 DartType computeType(Compiler compiler) { 420 DartType computeType(Compiler compiler) {
421 return compiler.doubleClass.computeType(compiler); 421 return compiler.doubleClass.computeType(compiler);
422 } 422 }
423 423
424 HType union(HType other) { 424 HType union(HType other, Compiler compiler) {
425 if (other.isConflicting()) return HType.DOUBLE; 425 if (other.isConflicting()) return HType.DOUBLE;
426 if (other.isUnknown()) return HType.UNKNOWN; 426 if (other.isUnknown()) return HType.UNKNOWN;
427 if (other.isDouble()) return HType.DOUBLE; 427 if (other.isDouble()) return HType.DOUBLE;
428 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL; 428 if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
429 if (other.isNumber()) return HType.NUMBER; 429 if (other.isNumber()) return HType.NUMBER;
430 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL; 430 if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
431 if (other.isNull()) return HType.DOUBLE_OR_NULL; 431 if (other.isNull()) return HType.DOUBLE_OR_NULL;
432 return HType.UNKNOWN; 432 return HType.UNKNOWN;
433 } 433 }
434 434
435 HType intersection(HType other) { 435 HType intersection(HType other, Compiler compiler) {
436 if (other.isConflicting()) return HType.CONFLICTING; 436 if (other.isConflicting()) return HType.CONFLICTING;
437 if (other.isUnknown()) return HType.DOUBLE; 437 if (other.isUnknown()) return HType.DOUBLE;
438 if (other.isIntegerOrNull()) return HType.CONFLICTING; 438 if (other.isIntegerOrNull()) return HType.CONFLICTING;
439 if (other.isInteger()) return HType.CONFLICTING; 439 if (other.isInteger()) return HType.CONFLICTING;
440 if (other.isDouble()) return HType.DOUBLE; 440 if (other.isDouble()) return HType.DOUBLE;
441 if (other.isDoubleOrNull()) return HType.DOUBLE; 441 if (other.isDoubleOrNull()) return HType.DOUBLE;
442 if (other.isNumber()) return HType.DOUBLE; 442 if (other.isNumber()) return HType.DOUBLE;
443 if (other.isNumberOrNull()) return HType.DOUBLE; 443 if (other.isNumberOrNull()) return HType.DOUBLE;
444 return HType.CONFLICTING; 444 return HType.CONFLICTING;
445 } 445 }
446 } 446 }
447 447
448 class HIndexablePrimitiveType extends HPrimitiveType { 448 class HIndexablePrimitiveType extends HPrimitiveType {
449 const HIndexablePrimitiveType(); 449 const HIndexablePrimitiveType();
450 bool isIndexablePrimitive() => true; 450 bool isIndexablePrimitive() => true;
451 String toString() => "indexable"; 451 String toString() => "indexable";
452 452
453 DartType computeType(Compiler compiler) { 453 DartType computeType(Compiler compiler) {
454 // TODO(ngeoffray): Represent union types. 454 // TODO(ngeoffray): Represent union types.
455 return null; 455 return null;
456 } 456 }
457 457
458 HType union(HType other) { 458 HType union(HType other, Compiler compiler) {
459 if (other.isConflicting()) return HType.INDEXABLE_PRIMITIVE; 459 if (other.isConflicting()) return HType.INDEXABLE_PRIMITIVE;
460 if (other.isUnknown()) return HType.UNKNOWN; 460 if (other.isUnknown()) return HType.UNKNOWN;
461 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; 461 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
462 if (other is HBoundedPotentialPrimitiveString) { 462 if (other is HBoundedPotentialPrimitiveString) {
463 // TODO(ngeoffray): Represent union types. 463 // TODO(ngeoffray): Represent union types.
464 return HType.UNKNOWN; 464 return HType.UNKNOWN;
465 } 465 }
466 if (other is HBoundedPotentialPrimitiveArray) { 466 if (other is HBoundedPotentialPrimitiveArray) {
467 // TODO(ngeoffray): Represent union types. 467 // TODO(ngeoffray): Represent union types.
468 return HType.UNKNOWN; 468 return HType.UNKNOWN;
469 } 469 }
470 return HType.UNKNOWN; 470 return HType.UNKNOWN;
471 } 471 }
472 472
473 HType intersection(HType other) { 473 HType intersection(HType other, Compiler compiler) {
474 if (other.isConflicting()) return HType.CONFLICTING; 474 if (other.isConflicting()) return HType.CONFLICTING;
475 if (other.isUnknown()) return HType.INDEXABLE_PRIMITIVE; 475 if (other.isUnknown()) return HType.INDEXABLE_PRIMITIVE;
476 if (other.isIndexablePrimitive()) return other; 476 if (other.isIndexablePrimitive()) return other;
477 if (other is HBoundedPotentialPrimitiveString) return HType.STRING; 477 if (other is HBoundedPotentialPrimitiveString) return HType.STRING;
478 if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY; 478 if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY;
479 return HType.CONFLICTING; 479 return HType.CONFLICTING;
480 } 480 }
481 } 481 }
482 482
483 class HStringOrNullType extends HPrimitiveOrNullType { 483 class HStringOrNullType extends HPrimitiveOrNullType {
484 const HStringOrNullType(); 484 const HStringOrNullType();
485 bool isStringOrNull() => true; 485 bool isStringOrNull() => true;
486 String toString() => "String or null"; 486 String toString() => "String or null";
487 487
488 DartType computeType(Compiler compiler) { 488 DartType computeType(Compiler compiler) {
489 return compiler.stringClass.computeType(compiler); 489 return compiler.stringClass.computeType(compiler);
490 } 490 }
491 491
492 HType union(HType other) { 492 HType union(HType other, Compiler compiler) {
493 if (other.isConflicting()) return HType.STRING_OR_NULL; 493 if (other.isConflicting()) return HType.STRING_OR_NULL;
494 if (other.isUnknown()) return HType.UNKNOWN; 494 if (other.isUnknown()) return HType.UNKNOWN;
495 if (other.isString()) return HType.STRING_OR_NULL; 495 if (other.isString()) return HType.STRING_OR_NULL;
496 if (other.isStringOrNull()) return HType.STRING_OR_NULL; 496 if (other.isStringOrNull()) return HType.STRING_OR_NULL;
497 if (other.isIndexablePrimitive()) { 497 if (other.isIndexablePrimitive()) {
498 // We don't have a type that represents the nullable indexable 498 // We don't have a type that represents the nullable indexable
499 // primitive. 499 // primitive.
500 return HType.UNKNOWN; 500 return HType.UNKNOWN;
501 } 501 }
502 if (other is HBoundedPotentialPrimitiveString) { 502 if (other is HBoundedPotentialPrimitiveString) {
503 if (other.canBeNull()) { 503 if (other.canBeNull()) {
504 return other; 504 return other;
505 } else { 505 } else {
506 HBoundedType boundedType = other; 506 HBoundedType boundedType = other;
507 return new HBoundedPotentialPrimitiveString(boundedType.type, true); 507 return new HBoundedPotentialPrimitiveString(boundedType.type, true);
508 } 508 }
509 } 509 }
510 if (other.isNull()) return HType.STRING_OR_NULL; 510 if (other.isNull()) return HType.STRING_OR_NULL;
511 return HType.UNKNOWN; 511 return HType.UNKNOWN;
512 } 512 }
513 513
514 HType intersection(HType other) { 514 HType intersection(HType other, Compiler compiler) {
515 if (other.isConflicting()) return HType.CONFLICTING; 515 if (other.isConflicting()) return HType.CONFLICTING;
516 if (other.isUnknown()) return HType.STRING_OR_NULL; 516 if (other.isUnknown()) return HType.STRING_OR_NULL;
517 if (other.isString()) return HType.STRING; 517 if (other.isString()) return HType.STRING;
518 if (other.isStringOrNull()) return HType.STRING_OR_NULL; 518 if (other.isStringOrNull()) return HType.STRING_OR_NULL;
519 if (other.isArray()) return HType.CONFLICTING; 519 if (other.isArray()) return HType.CONFLICTING;
520 if (other.isIndexablePrimitive()) return HType.STRING; 520 if (other.isIndexablePrimitive()) return HType.STRING;
521 if (other is HBoundedPotentialPrimitiveString) { 521 if (other is HBoundedPotentialPrimitiveString) {
522 return other.canBeNull() ? HType.STRING_OR_NULL : HType.STRING; 522 return other.canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
523 } 523 }
524 if (other.canBeNull()) return HType.NULL; 524 if (other.canBeNull()) return HType.NULL;
525 return HType.CONFLICTING; 525 return HType.CONFLICTING;
526 } 526 }
527 } 527 }
528 528
529 class HStringType extends HIndexablePrimitiveType { 529 class HStringType extends HIndexablePrimitiveType {
530 const HStringType(); 530 const HStringType();
531 bool isString() => true; 531 bool isString() => true;
532 String toString() => "String"; 532 String toString() => "String";
533 533
534 DartType computeType(Compiler compiler) { 534 DartType computeType(Compiler compiler) {
535 return compiler.stringClass.computeType(compiler); 535 return compiler.stringClass.computeType(compiler);
536 } 536 }
537 537
538 HType union(HType other) { 538 HType union(HType other, Compiler compiler) {
539 if (other.isConflicting()) return HType.STRING; 539 if (other.isConflicting()) return HType.STRING;
540 if (other.isUnknown()) return HType.UNKNOWN; 540 if (other.isUnknown()) return HType.UNKNOWN;
541 if (other.isString()) return HType.STRING; 541 if (other.isString()) return HType.STRING;
542 if (other.isStringOrNull()) return HType.STRING_OR_NULL; 542 if (other.isStringOrNull()) return HType.STRING_OR_NULL;
543 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; 543 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
544 if (other is HBoundedPotentialPrimitiveString) return other; 544 if (other is HBoundedPotentialPrimitiveString) return other;
545 if (other.isNull()) return HType.STRING_OR_NULL; 545 if (other.isNull()) return HType.STRING_OR_NULL;
546 return HType.UNKNOWN; 546 return HType.UNKNOWN;
547 } 547 }
548 548
549 HType intersection(HType other) { 549 HType intersection(HType other, Compiler compiler) {
550 if (other.isConflicting()) return HType.CONFLICTING; 550 if (other.isConflicting()) return HType.CONFLICTING;
551 if (other.isUnknown()) return HType.STRING; 551 if (other.isUnknown()) return HType.STRING;
552 if (other.isString()) return HType.STRING; 552 if (other.isString()) return HType.STRING;
553 if (other.isArray()) return HType.CONFLICTING; 553 if (other.isArray()) return HType.CONFLICTING;
554 if (other.isIndexablePrimitive()) return HType.STRING; 554 if (other.isIndexablePrimitive()) return HType.STRING;
555 if (other.isStringOrNull()) return HType.STRING; 555 if (other.isStringOrNull()) return HType.STRING;
556 if (other is HBoundedPotentialPrimitiveString) return HType.STRING; 556 if (other is HBoundedPotentialPrimitiveString) return HType.STRING;
557 return HType.CONFLICTING; 557 return HType.CONFLICTING;
558 } 558 }
559 } 559 }
560 560
561 class HReadableArrayType extends HIndexablePrimitiveType { 561 class HReadableArrayType extends HIndexablePrimitiveType {
562 const HReadableArrayType(); 562 const HReadableArrayType();
563 bool isReadableArray() => true; 563 bool isReadableArray() => true;
564 String toString() => "readable array"; 564 String toString() => "readable array";
565 565
566 DartType computeType(Compiler compiler) { 566 DartType computeType(Compiler compiler) {
567 return compiler.listClass.computeType(compiler); 567 return compiler.listClass.computeType(compiler);
568 } 568 }
569 569
570 HType union(HType other) { 570 HType union(HType other, Compiler compiler) {
571 if (other.isConflicting()) return HType.READABLE_ARRAY; 571 if (other.isConflicting()) return HType.READABLE_ARRAY;
572 if (other.isUnknown()) return HType.UNKNOWN; 572 if (other.isUnknown()) return HType.UNKNOWN;
573 if (other.isReadableArray()) return HType.READABLE_ARRAY; 573 if (other.isReadableArray()) return HType.READABLE_ARRAY;
574 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; 574 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
575 if (other is HBoundedPotentialPrimitiveArray) return other; 575 if (other is HBoundedPotentialPrimitiveArray) return other;
576 return HType.UNKNOWN; 576 return HType.UNKNOWN;
577 } 577 }
578 578
579 HType intersection(HType other) { 579 HType intersection(HType other, Compiler compiler) {
580 if (other.isConflicting()) return HType.CONFLICTING; 580 if (other.isConflicting()) return HType.CONFLICTING;
581 if (other.isUnknown()) return HType.READABLE_ARRAY; 581 if (other.isUnknown()) return HType.READABLE_ARRAY;
582 if (other.isString()) return HType.CONFLICTING; 582 if (other.isString()) return HType.CONFLICTING;
583 if (other.isReadableArray()) return other; 583 if (other.isReadableArray()) return other;
584 if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY; 584 if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY;
585 if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY; 585 if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY;
586 return HType.CONFLICTING; 586 return HType.CONFLICTING;
587 } 587 }
588 } 588 }
589 589
590 class HMutableArrayType extends HReadableArrayType { 590 class HMutableArrayType extends HReadableArrayType {
591 const HMutableArrayType(); 591 const HMutableArrayType();
592 bool isMutableArray() => true; 592 bool isMutableArray() => true;
593 String toString() => "mutable array"; 593 String toString() => "mutable array";
594 594
595 HType union(HType other) { 595 HType union(HType other, Compiler compiler) {
596 if (other.isConflicting()) return HType.MUTABLE_ARRAY; 596 if (other.isConflicting()) return HType.MUTABLE_ARRAY;
597 if (other.isUnknown()) return HType.UNKNOWN; 597 if (other.isUnknown()) return HType.UNKNOWN;
598 if (other.isMutableArray()) return HType.MUTABLE_ARRAY; 598 if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
599 if (other.isReadableArray()) return HType.READABLE_ARRAY; 599 if (other.isReadableArray()) return HType.READABLE_ARRAY;
600 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; 600 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
601 if (other is HBoundedPotentialPrimitiveArray) return other; 601 if (other is HBoundedPotentialPrimitiveArray) return other;
602 return HType.UNKNOWN; 602 return HType.UNKNOWN;
603 } 603 }
604 604
605 HType intersection(HType other) { 605 HType intersection(HType other, Compiler compiler) {
606 if (other.isConflicting()) return HType.CONFLICTING; 606 if (other.isConflicting()) return HType.CONFLICTING;
607 if (other.isUnknown()) return HType.MUTABLE_ARRAY; 607 if (other.isUnknown()) return HType.MUTABLE_ARRAY;
608 if (other.isMutableArray()) return other; 608 if (other.isMutableArray()) return other;
609 if (other.isString()) return HType.CONFLICTING; 609 if (other.isString()) return HType.CONFLICTING;
610 if (other.isIndexablePrimitive()) return HType.MUTABLE_ARRAY; 610 if (other.isIndexablePrimitive()) return HType.MUTABLE_ARRAY;
611 if (other is HBoundedPotentialPrimitiveArray) return HType.MUTABLE_ARRAY; 611 if (other is HBoundedPotentialPrimitiveArray) return HType.MUTABLE_ARRAY;
612 return HType.CONFLICTING; 612 return HType.CONFLICTING;
613 } 613 }
614 } 614 }
615 615
616 class HFixedArrayType extends HMutableArrayType { 616 class HFixedArrayType extends HMutableArrayType {
617 const HFixedArrayType(); 617 const HFixedArrayType();
618 bool isFixedArray() => true; 618 bool isFixedArray() => true;
619 String toString() => "fixed array"; 619 String toString() => "fixed array";
620 620
621 HType union(HType other) { 621 HType union(HType other, Compiler compiler) {
622 if (other.isConflicting()) return HType.FIXED_ARRAY; 622 if (other.isConflicting()) return HType.FIXED_ARRAY;
623 if (other.isUnknown()) return HType.UNKNOWN; 623 if (other.isUnknown()) return HType.UNKNOWN;
624 if (other.isFixedArray()) return HType.FIXED_ARRAY; 624 if (other.isFixedArray()) return HType.FIXED_ARRAY;
625 if (other.isMutableArray()) return HType.MUTABLE_ARRAY; 625 if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
626 if (other.isReadableArray()) return HType.READABLE_ARRAY; 626 if (other.isReadableArray()) return HType.READABLE_ARRAY;
627 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; 627 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
628 if (other is HBoundedPotentialPrimitiveArray) return other; 628 if (other is HBoundedPotentialPrimitiveArray) return other;
629 return HType.UNKNOWN; 629 return HType.UNKNOWN;
630 } 630 }
631 631
632 HType intersection(HType other) { 632 HType intersection(HType other, Compiler compiler) {
633 if (other.isConflicting()) return HType.CONFLICTING; 633 if (other.isConflicting()) return HType.CONFLICTING;
634 if (other.isUnknown()) return HType.FIXED_ARRAY; 634 if (other.isUnknown()) return HType.FIXED_ARRAY;
635 if (other.isFixedArray()) return HType.FIXED_ARRAY; 635 if (other.isFixedArray()) return HType.FIXED_ARRAY;
636 if (other.isExtendableArray()) return HType.CONFLICTING; 636 if (other.isExtendableArray()) return HType.CONFLICTING;
637 if (other.isString()) return HType.CONFLICTING; 637 if (other.isString()) return HType.CONFLICTING;
638 if (other.isIndexablePrimitive()) return HType.FIXED_ARRAY; 638 if (other.isIndexablePrimitive()) return HType.FIXED_ARRAY;
639 if (other is HBoundedPotentialPrimitiveArray) return HType.FIXED_ARRAY; 639 if (other is HBoundedPotentialPrimitiveArray) return HType.FIXED_ARRAY;
640 return HType.CONFLICTING; 640 return HType.CONFLICTING;
641 } 641 }
642 } 642 }
643 643
644 class HExtendableArrayType extends HMutableArrayType { 644 class HExtendableArrayType extends HMutableArrayType {
645 const HExtendableArrayType(); 645 const HExtendableArrayType();
646 bool isExtendableArray() => true; 646 bool isExtendableArray() => true;
647 String toString() => "extendable array"; 647 String toString() => "extendable array";
648 648
649 HType union(HType other) { 649 HType union(HType other, Compiler compiler) {
650 if (other.isConflicting()) return HType.EXTENDABLE_ARRAY; 650 if (other.isConflicting()) return HType.EXTENDABLE_ARRAY;
651 if (other.isUnknown()) return HType.UNKNOWN; 651 if (other.isUnknown()) return HType.UNKNOWN;
652 if (other.isExtendableArray()) return HType.EXTENDABLE_ARRAY; 652 if (other.isExtendableArray()) return HType.EXTENDABLE_ARRAY;
653 if (other.isMutableArray()) return HType.MUTABLE_ARRAY; 653 if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
654 if (other.isReadableArray()) return HType.READABLE_ARRAY; 654 if (other.isReadableArray()) return HType.READABLE_ARRAY;
655 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE; 655 if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
656 if (other is HBoundedPotentialPrimitiveArray) return other; 656 if (other is HBoundedPotentialPrimitiveArray) return other;
657 return HType.UNKNOWN; 657 return HType.UNKNOWN;
658 } 658 }
659 659
660 HType intersection(HType other) { 660 HType intersection(HType other, Compiler compiler) {
661 if (other.isConflicting()) return HType.CONFLICTING; 661 if (other.isConflicting()) return HType.CONFLICTING;
662 if (other.isUnknown()) return HType.EXTENDABLE_ARRAY; 662 if (other.isUnknown()) return HType.EXTENDABLE_ARRAY;
663 if (other.isExtendableArray()) return HType.EXTENDABLE_ARRAY; 663 if (other.isExtendableArray()) return HType.EXTENDABLE_ARRAY;
664 if (other.isString()) return HType.CONFLICTING; 664 if (other.isString()) return HType.CONFLICTING;
665 if (other.isFixedArray()) return HType.CONFLICTING; 665 if (other.isFixedArray()) return HType.CONFLICTING;
666 if (other.isIndexablePrimitive()) return HType.EXTENDABLE_ARRAY; 666 if (other.isIndexablePrimitive()) return HType.EXTENDABLE_ARRAY;
667 if (other is HBoundedPotentialPrimitiveArray) return HType.EXTENDABLE_ARRAY; 667 if (other is HBoundedPotentialPrimitiveArray) return HType.EXTENDABLE_ARRAY;
668 return HType.CONFLICTING; 668 return HType.CONFLICTING;
669 } 669 }
670 } 670 }
(...skipping 19 matching lines...) Expand all
690 const HBoundedType.nonNull(DartType type) : this(type); 690 const HBoundedType.nonNull(DartType type) : this(type);
691 691
692 DartType computeType(Compiler compiler) => type; 692 DartType computeType(Compiler compiler) => type;
693 693
694 Element lookupMember(SourceString name) { 694 Element lookupMember(SourceString name) {
695 if (!isExact()) return null; 695 if (!isExact()) return null;
696 ClassElement classElement = type.element; 696 ClassElement classElement = type.element;
697 return classElement.lookupMember(name); 697 return classElement.lookupMember(name);
698 } 698 }
699 699
700 HType intersection(HType other) { 700 HType intersection(HType other, Compiler compiler) {
701 assert(!(isExact() && canBeNull())); 701 assert(!(isExact() && canBeNull()));
702 if (other.isConflicting()) return HType.CONFLICTING; 702 if (other.isConflicting()) return HType.CONFLICTING;
703 if (other.isNull()) return canBeNull() ? HType.NULL : HType.CONFLICTING; 703 if (other.isNull()) return canBeNull() ? HType.NULL : HType.CONFLICTING;
704
704 if (other is HBoundedType) { 705 if (other is HBoundedType) {
705 HBoundedType temp = other; 706 HBoundedType temp = other;
706 if (identical(this.type, temp.type)) { 707 if (identical(this.type, temp.type)) {
708 // If the types are the same, we return the [HBoundedType]
709 // that has the most restrictive representation: if it's exact
710 // (eg cannot be a subtype), and if it cannot be null.
707 if (isExact()) { 711 if (isExact()) {
708 return this; 712 return this;
709 } else if (other.isExact()) { 713 } else if (other.isExact()) {
710 return other; 714 return other;
711 } else if (canBeNull()) { 715 } else if (canBeNull()) {
712 return other; 716 return other;
713 } else { 717 } else {
714 return this; 718 return this;
715 } 719 }
720 // If one type is a subtype of the other, we return the former,
721 // which is the narrower type.
722 } else if (compiler.types.isSubtype(type, other.type)) {
723 return this;
724 } else if (compiler.types.isSubtype(other.type, type)) {
725 return other;
716 } 726 }
717 } 727 }
718 if (other.isUnknown()) return this; 728 if (other.isUnknown()) return this;
719 if (other.canBeNull() && canBeNull()) return HType.NULL; 729 if (other.canBeNull() && canBeNull()) return HType.NULL;
720 return HType.CONFLICTING; 730 return HType.CONFLICTING;
721 } 731 }
722 732
723 bool operator ==(HType other) { 733 bool operator ==(HType other) {
724 if (other is !HBoundedType) return false; 734 if (other is !HBoundedType) return false;
725 HBoundedType bounded = other; 735 HBoundedType bounded = other;
726 return (identical(type, bounded.type) && identical(canBeNull(), bounded.canB eNull()) 736 return (identical(type, bounded.type)
727 && identical(isExact(), other .isExact())); 737 && identical(canBeNull(), bounded.canBeNull())
738 && identical(isExact(), other.isExact()));
728 } 739 }
729 740
730 HType union(HType other) { 741 HType union(HType other, Compiler compiler) {
731 if (other.isNull()) { 742 if (other.isNull()) {
732 if (canBeNull()) { 743 if (canBeNull()) {
733 return this; 744 return this;
734 } else { 745 } else {
735 return new HBoundedType.withNull(type); 746 return new HBoundedType.withNull(type);
736 } 747 }
737 } 748 }
738 if (other is HBoundedType) { 749 if (other is HBoundedType) {
739 HBoundedType temp = other; 750 HBoundedType temp = other;
740 if (!identical(type, temp.type)) return HType.UNKNOWN; 751 if (!identical(type, temp.type)) return HType.UNKNOWN;
(...skipping 10 matching lines...) Expand all
751 const HBoundedPotentialPrimitiveType(DartType type, bool canBeNull) 762 const HBoundedPotentialPrimitiveType(DartType type, bool canBeNull)
752 : super(type, canBeNull, false); 763 : super(type, canBeNull, false);
753 bool canBePrimitive() => true; 764 bool canBePrimitive() => true;
754 } 765 }
755 766
756 class HBoundedPotentialPrimitiveNumberOrString 767 class HBoundedPotentialPrimitiveNumberOrString
757 extends HBoundedPotentialPrimitiveType { 768 extends HBoundedPotentialPrimitiveType {
758 const HBoundedPotentialPrimitiveNumberOrString(DartType type, bool canBeNull) 769 const HBoundedPotentialPrimitiveNumberOrString(DartType type, bool canBeNull)
759 : super(type, canBeNull); 770 : super(type, canBeNull);
760 771
761 HType union(HType other) { 772 HType union(HType other, Compiler compiler) {
762 if (other.isNumber()) return this; 773 if (other.isNumber()) return this;
763 if (other.isNumberOrNull()) { 774 if (other.isNumberOrNull()) {
764 if (canBeNull()) return this; 775 if (canBeNull()) return this;
765 return new HBoundedPotentialPrimitiveNumberOrString(type, true); 776 return new HBoundedPotentialPrimitiveNumberOrString(type, true);
766 } 777 }
767 778
768 if (other.isString()) return this; 779 if (other.isString()) return this;
769 if (other.isStringOrNull()) { 780 if (other.isStringOrNull()) {
770 if (canBeNull()) return this; 781 if (canBeNull()) return this;
771 return new HBoundedPotentialPrimitiveNumberOrString(type, true); 782 return new HBoundedPotentialPrimitiveNumberOrString(type, true);
772 } 783 }
773 784
774 if (other.isNull()) { 785 if (other.isNull()) {
775 if (canBeNull()) return this; 786 if (canBeNull()) return this;
776 return new HBoundedPotentialPrimitiveNumberOrString(type, true); 787 return new HBoundedPotentialPrimitiveNumberOrString(type, true);
777 } 788 }
778 789
779 return super.union(other); 790 return super.union(other, compiler);
780 } 791 }
781 792
782 HType intersection(HType other) { 793 HType intersection(HType other, Compiler compiler) {
783 if (other.isNumber()) return other; 794 if (other.isNumber()) return other;
784 if (other.isNumberOrNull()) { 795 if (other.isNumberOrNull()) {
785 if (!canBeNull()) return HType.NUMBER; 796 if (!canBeNull()) return HType.NUMBER;
786 return other; 797 return other;
787 } 798 }
788 if (other.isString()) return other; 799 if (other.isString()) return other;
789 if (other.isStringOrNull()) { 800 if (other.isStringOrNull()) {
790 if (!canBeNull()) return HType.STRING; 801 if (!canBeNull()) return HType.STRING;
791 return other; 802 return other;
792 } 803 }
793 return super.intersection(other); 804 return super.intersection(other, compiler);
794 } 805 }
795 } 806 }
796 807
797 class HBoundedPotentialPrimitiveArray extends HBoundedPotentialPrimitiveType { 808 class HBoundedPotentialPrimitiveArray extends HBoundedPotentialPrimitiveType {
798 const HBoundedPotentialPrimitiveArray(DartType type, bool canBeNull) 809 const HBoundedPotentialPrimitiveArray(DartType type, bool canBeNull)
799 : super(type, canBeNull); 810 : super(type, canBeNull);
800 811
801 HType union(HType other) { 812 HType union(HType other, Compiler compiler) {
802 if (other.isString()) return HType.UNKNOWN; 813 if (other.isString()) return HType.UNKNOWN;
803 if (other.isReadableArray()) return this; 814 if (other.isReadableArray()) return this;
804 // TODO(ngeoffray): implement union types. 815 // TODO(ngeoffray): implement union types.
805 if (other.isIndexablePrimitive()) return HType.UNKNOWN; 816 if (other.isIndexablePrimitive()) return HType.UNKNOWN;
806 if (other.isNull()) { 817 if (other.isNull()) {
807 if (canBeNull()) { 818 if (canBeNull()) {
808 return this; 819 return this;
809 } else { 820 } else {
810 return new HBoundedPotentialPrimitiveArray(type, true); 821 return new HBoundedPotentialPrimitiveArray(type, true);
811 } 822 }
812 } 823 }
813 return super.union(other); 824 return super.union(other, compiler);
814 } 825 }
815 826
816 HType intersection(HType other) { 827 HType intersection(HType other, Compiler compiler) {
817 if (other.isConflicting()) return HType.CONFLICTING; 828 if (other.isConflicting()) return HType.CONFLICTING;
818 if (other.isString()) return HType.CONFLICTING; 829 if (other.isString()) return HType.CONFLICTING;
819 if (other.isReadableArray()) return other; 830 if (other.isReadableArray()) return other;
820 if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY; 831 if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY;
821 return super.intersection(other); 832 return super.intersection(other, compiler);
822 } 833 }
823 } 834 }
824 835
825 class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType { 836 class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType {
826 const HBoundedPotentialPrimitiveString(DartType type, bool canBeNull) 837 const HBoundedPotentialPrimitiveString(DartType type, bool canBeNull)
827 : super(type, canBeNull); 838 : super(type, canBeNull);
828 839
829 bool isPrimitiveOrNull() => true; 840 bool isPrimitiveOrNull() => true;
830 841
831 HType union(HType other) { 842 HType union(HType other, Compiler compiler) {
832 if (other.isString()) return this; 843 if (other.isString()) return this;
833 if (other.isStringOrNull()) { 844 if (other.isStringOrNull()) {
834 if (canBeNull()) { 845 if (canBeNull()) {
835 return this; 846 return this;
836 } else { 847 } else {
837 return new HBoundedPotentialPrimitiveString(type, true); 848 return new HBoundedPotentialPrimitiveString(type, true);
838 } 849 }
839 } 850 }
840 if (other.isNull()) { 851 if (other.isNull()) {
841 if (canBeNull()) { 852 if (canBeNull()) {
842 return this; 853 return this;
843 } else { 854 } else {
844 return new HBoundedPotentialPrimitiveString(type, true); 855 return new HBoundedPotentialPrimitiveString(type, true);
845 } 856 }
846 } 857 }
847 // TODO(ngeoffray): implement union types. 858 // TODO(ngeoffray): implement union types.
848 if (other.isIndexablePrimitive()) return HType.UNKNOWN; 859 if (other.isIndexablePrimitive()) return HType.UNKNOWN;
849 return super.union(other); 860 return super.union(other, compiler);
850 } 861 }
851 862
852 HType intersection(HType other) { 863 HType intersection(HType other, Compiler compiler) {
853 if (other.isConflicting()) return HType.CONFLICTING; 864 if (other.isConflicting()) return HType.CONFLICTING;
854 if (other.isString()) return HType.STRING; 865 if (other.isString()) return HType.STRING;
855 if (other.isStringOrNull()) { 866 if (other.isStringOrNull()) {
856 return canBeNull() ? HType.STRING_OR_NULL : HType.STRING; 867 return canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
857 } 868 }
858 if (other.isReadableArray()) return HType.CONFLICTING; 869 if (other.isReadableArray()) return HType.CONFLICTING;
859 if (other.isIndexablePrimitive()) return HType.STRING; 870 if (other.isIndexablePrimitive()) return HType.STRING;
860 return super.intersection(other); 871 return super.intersection(other, compiler);
861 } 872 }
862 } 873 }
863 874
864 class HTypeMap { 875 class HTypeMap {
865 Map<HInstruction, HType> _map; 876 Map<HInstruction, HType> _map;
866 877
867 HTypeMap() : _map = new Map<HInstruction, HType>(); 878 HTypeMap() : _map = new Map<HInstruction, HType>();
868 879
869 operator [](HInstruction instruction) { 880 operator [](HInstruction instruction) {
870 HType result = _map[instruction]; 881 HType result = _map[instruction];
871 if (result == null) return instruction.guaranteedType; 882 if (result == null) return instruction.guaranteedType;
872 return result; 883 return result;
873 } 884 }
874 885
875 operator []=(HInstruction instruction, HType value) { 886 operator []=(HInstruction instruction, HType value) {
876 _map[instruction] = value; 887 _map[instruction] = value;
877 } 888 }
878 } 889 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/optimize.dart ('k') | lib/compiler/implementation/ssa/types_propagation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698