| 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 |