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 masks; | 5 part of masks; |
6 | 6 |
7 class UnionTypeMask implements TypeMask { | 7 class UnionTypeMask implements TypeMask { |
8 final Iterable<FlatTypeMask> disjointMasks; | 8 final Iterable<FlatTypeMask> disjointMasks; |
9 | 9 |
10 static const int MAX_UNION_LENGTH = 4; | 10 static const int MAX_UNION_LENGTH = 4; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 } | 87 } |
88 } | 88 } |
89 | 89 |
90 static TypeMask flatten(List<FlatTypeMask> masks, ClosedWorld closedWorld) { | 90 static TypeMask flatten(List<FlatTypeMask> masks, ClosedWorld closedWorld) { |
91 assert(masks.length > 1); | 91 assert(masks.length > 1); |
92 // If either type mask is a subtype type mask, we cannot use a | 92 // If either type mask is a subtype type mask, we cannot use a |
93 // subclass type mask to represent their union. | 93 // subclass type mask to represent their union. |
94 bool useSubclass = masks.every((e) => !e.isSubtype); | 94 bool useSubclass = masks.every((e) => !e.isSubtype); |
95 bool isNullable = masks.any((e) => e.isNullable); | 95 bool isNullable = masks.any((e) => e.isNullable); |
96 | 96 |
97 List<ClassElement> masksBases = masks.map((mask) => mask.base).toList(); | 97 List masksBases = masks.map((mask) => mask.base).toList(); |
98 Iterable<ClassElement> candidates = | 98 Iterable<Entity> candidates = closedWorld.commonSupertypesOf(masksBases); |
99 closedWorld.commonSupertypesOf(masksBases); | |
100 | 99 |
101 // Compute the best candidate and its kind. | 100 // Compute the best candidate and its kind. |
102 ClassElement bestElement; | 101 Entity bestElement; |
103 int bestKind; | 102 int bestKind; |
104 int bestSize; | 103 int bestSize; |
105 for (ClassElement candidate in candidates) { | 104 for (Entity candidate in candidates) { |
106 bool isInstantiatedStrictSubclass(cls) => | 105 bool isInstantiatedStrictSubclass(cls) => |
107 cls != candidate && | 106 cls != candidate && |
108 closedWorld.isDirectlyInstantiated(cls) && | 107 closedWorld.isDirectlyInstantiated(cls) && |
109 closedWorld.isSubclassOf(cls, candidate); | 108 closedWorld.isSubclassOf(cls, candidate); |
110 | 109 |
111 int size; | 110 int size; |
112 int kind; | 111 int kind; |
113 if (useSubclass && masksBases.every(isInstantiatedStrictSubclass)) { | 112 if (useSubclass && masksBases.every(isInstantiatedStrictSubclass)) { |
114 // If both [this] and [other] are subclasses of the supertype, | 113 // If both [this] and [other] are subclasses of the supertype, |
115 // then we prefer to construct a subclass type mask because it | 114 // then we prefer to construct a subclass type mask because it |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 // The fast test is precise for exact types. | 223 // The fast test is precise for exact types. |
225 if (other.isExact) return false; | 224 if (other.isExact) return false; |
226 // We cannot contain object. | 225 // We cannot contain object. |
227 if (other.contains(closedWorld.coreClasses.objectClass, closedWorld)) { | 226 if (other.contains(closedWorld.coreClasses.objectClass, closedWorld)) { |
228 return false; | 227 return false; |
229 } | 228 } |
230 FlatTypeMask flat = TypeMask.nonForwardingMask(other); | 229 FlatTypeMask flat = TypeMask.nonForwardingMask(other); |
231 // Check we cover the base class. | 230 // Check we cover the base class. |
232 if (!contains(flat.base, closedWorld)) return false; | 231 if (!contains(flat.base, closedWorld)) return false; |
233 // Check for other members. | 232 // Check for other members. |
234 Iterable<ClassElement> members; | 233 Iterable<Entity> members; |
235 if (flat.isSubclass) { | 234 if (flat.isSubclass) { |
236 members = closedWorld.strictSubclassesOf(flat.base); | 235 members = closedWorld.strictSubclassesOf(flat.base); |
237 } else { | 236 } else { |
238 assert(flat.isSubtype); | 237 assert(flat.isSubtype); |
239 members = closedWorld.strictSubtypesOf(flat.base); | 238 members = closedWorld.strictSubtypesOf(flat.base); |
240 } | 239 } |
241 return members.every((ClassElement cls) => this.contains(cls, closedWorld)); | 240 return members.every((Entity cls) => this.contains(cls, closedWorld)); |
242 } | 241 } |
243 | 242 |
244 bool isInMask(TypeMask other, ClosedWorld closedWorld) { | 243 bool isInMask(TypeMask other, ClosedWorld closedWorld) { |
245 other = TypeMask.nonForwardingMask(other); | 244 other = TypeMask.nonForwardingMask(other); |
246 if (isNullable && !other.isNullable) return false; | 245 if (isNullable && !other.isNullable) return false; |
247 if (other.isUnion) { | 246 if (other.isUnion) { |
248 UnionTypeMask union = other; | 247 UnionTypeMask union = other; |
249 bool containedInAnyOf(FlatTypeMask mask, Iterable<FlatTypeMask> masks) { | 248 bool containedInAnyOf(FlatTypeMask mask, Iterable<FlatTypeMask> masks) { |
250 // null is not canonicalized for the union but stored only on some | 249 // null is not canonicalized for the union but stored only on some |
251 // masks in [disjointMask]. It has been checked in the surrounding | 250 // masks in [disjointMask]. It has been checked in the surrounding |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 } | 298 } |
300 | 299 |
301 bool containsOnlyBool(ClosedWorld closedWorld) { | 300 bool containsOnlyBool(ClosedWorld closedWorld) { |
302 return disjointMasks.every((mask) => mask.containsOnlyBool(closedWorld)); | 301 return disjointMasks.every((mask) => mask.containsOnlyBool(closedWorld)); |
303 } | 302 } |
304 | 303 |
305 bool containsOnlyString(ClosedWorld closedWorld) { | 304 bool containsOnlyString(ClosedWorld closedWorld) { |
306 return disjointMasks.every((mask) => mask.containsOnlyString(closedWorld)); | 305 return disjointMasks.every((mask) => mask.containsOnlyString(closedWorld)); |
307 } | 306 } |
308 | 307 |
309 bool containsOnly(ClassElement element) { | 308 bool containsOnly(Entity element) { |
310 return disjointMasks.every((mask) => mask.containsOnly(element)); | 309 return disjointMasks.every((mask) => mask.containsOnly(element)); |
311 } | 310 } |
312 | 311 |
313 bool satisfies(ClassElement cls, ClosedWorld closedWorld) { | 312 bool satisfies(Entity cls, ClosedWorld closedWorld) { |
314 return disjointMasks.every((mask) => mask.satisfies(cls, closedWorld)); | 313 return disjointMasks.every((mask) => mask.satisfies(cls, closedWorld)); |
315 } | 314 } |
316 | 315 |
317 bool contains(ClassElement type, ClosedWorld closedWorld) { | 316 bool contains(Entity cls, ClosedWorld closedWorld) { |
318 return disjointMasks.any((e) => e.contains(type, closedWorld)); | 317 return disjointMasks.any((e) => e.contains(cls, closedWorld)); |
319 } | 318 } |
320 | 319 |
321 bool containsAll(ClosedWorld closedWorld) { | 320 bool containsAll(ClosedWorld closedWorld) { |
322 return disjointMasks.any((mask) => mask.containsAll(closedWorld)); | 321 return disjointMasks.any((mask) => mask.containsAll(closedWorld)); |
323 } | 322 } |
324 | 323 |
325 ClassElement singleClass(ClosedWorld closedWorld) => null; | 324 Entity singleClass(ClosedWorld closedWorld) => null; |
326 | 325 |
327 bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) { | 326 bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) { |
328 return disjointMasks | 327 return disjointMasks |
329 .any((e) => e.needsNoSuchMethodHandling(selector, closedWorld)); | 328 .any((e) => e.needsNoSuchMethodHandling(selector, closedWorld)); |
330 } | 329 } |
331 | 330 |
332 bool canHit(Element element, Selector selector, ClosedWorld closedWorld) { | 331 bool canHit(Element element, Selector selector, ClosedWorld closedWorld) { |
333 return disjointMasks.any((e) => e.canHit(element, selector, closedWorld)); | 332 return disjointMasks.any((e) => e.canHit(element, selector, closedWorld)); |
334 } | 333 } |
335 | 334 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 int get hashCode { | 373 int get hashCode { |
375 int hashCode = isNullable ? 86 : 43; | 374 int hashCode = isNullable ? 86 : 43; |
376 // The order of the masks in [disjointMasks] must not affect the | 375 // The order of the masks in [disjointMasks] must not affect the |
377 // hashCode. | 376 // hashCode. |
378 for (var mask in disjointMasks) { | 377 for (var mask in disjointMasks) { |
379 hashCode = (hashCode ^ mask.nonNullable().hashCode) & 0x3fffffff; | 378 hashCode = (hashCode ^ mask.nonNullable().hashCode) & 0x3fffffff; |
380 } | 379 } |
381 return hashCode; | 380 return hashCode; |
382 } | 381 } |
383 } | 382 } |
OLD | NEW |