| 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 /// An implementation of a [UniverseSelectorConstraints] that is consists if an
only | 7 /// An implementation of a [UniverseSelectorConstraints] that is consists if an
only |
| 8 /// increasing set of [TypeMask]s, that is, once a mask is added it cannot be | 8 /// increasing set of [TypeMask]s, that is, once a mask is added it cannot be |
| 9 /// removed. | 9 /// removed. |
| 10 class IncreasingTypeMaskSet extends UniverseSelectorConstraints { | 10 class IncreasingTypeMaskSet extends UniverseSelectorConstraints { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 } | 70 } |
| 71 } | 71 } |
| 72 | 72 |
| 73 /** | 73 /** |
| 74 * A type mask represents a set of contained classes, but the | 74 * A type mask represents a set of contained classes, but the |
| 75 * operations on it are not guaranteed to be precise and they may | 75 * operations on it are not guaranteed to be precise and they may |
| 76 * yield conservative answers that contain too many classes. | 76 * yield conservative answers that contain too many classes. |
| 77 */ | 77 */ |
| 78 abstract class TypeMask implements ReceiverConstraint, AbstractValue { | 78 abstract class TypeMask implements ReceiverConstraint, AbstractValue { |
| 79 factory TypeMask( | 79 factory TypeMask( |
| 80 ClassElement base, int kind, bool isNullable, ClosedWorld closedWorld) { | 80 Entity base, int kind, bool isNullable, ClosedWorld closedWorld) { |
| 81 return new FlatTypeMask.normalized( | 81 return new FlatTypeMask.normalized( |
| 82 base, (kind << 1) | (isNullable ? 1 : 0), closedWorld); | 82 base, (kind << 1) | (isNullable ? 1 : 0), closedWorld); |
| 83 } | 83 } |
| 84 | 84 |
| 85 const factory TypeMask.empty() = FlatTypeMask.empty; | 85 const factory TypeMask.empty() = FlatTypeMask.empty; |
| 86 | 86 |
| 87 factory TypeMask.exact(ClassElement base, ClosedWorld closedWorld) { | 87 factory TypeMask.exact(Entity base, ClosedWorld closedWorld) { |
| 88 assert(invariant(base, closedWorld.isInstantiated(base), | 88 assert(invariant(base, closedWorld.isInstantiated(base), |
| 89 message: () => "Cannot create exact type mask for uninstantiated " | 89 message: () => "Cannot create exact type mask for uninstantiated " |
| 90 "class $base.\n${closedWorld.dump(base)}")); | 90 "class $base.\n${closedWorld.dump(base)}")); |
| 91 return new FlatTypeMask.exact(base); | 91 return new FlatTypeMask.exact(base); |
| 92 } | 92 } |
| 93 | 93 |
| 94 factory TypeMask.exactOrEmpty(ClassElement base, ClosedWorld closedWorld) { | 94 factory TypeMask.exactOrEmpty(Entity base, ClosedWorld closedWorld) { |
| 95 if (closedWorld.isInstantiated(base)) return new FlatTypeMask.exact(base); | 95 if (closedWorld.isInstantiated(base)) return new FlatTypeMask.exact(base); |
| 96 return const TypeMask.empty(); | 96 return const TypeMask.empty(); |
| 97 } | 97 } |
| 98 | 98 |
| 99 factory TypeMask.subclass(ClassElement base, ClosedWorld closedWorld) { | 99 factory TypeMask.subclass(Entity base, ClosedWorld closedWorld) { |
| 100 assert(invariant(base, closedWorld.isInstantiated(base), | 100 assert(invariant(base, closedWorld.isInstantiated(base), |
| 101 message: () => "Cannot create subclass type mask for uninstantiated " | 101 message: () => "Cannot create subclass type mask for uninstantiated " |
| 102 "class $base.\n${closedWorld.dump(base)}")); | 102 "class $base.\n${closedWorld.dump(base)}")); |
| 103 ClassElement topmost = closedWorld.getLubOfInstantiatedSubclasses(base); | 103 Entity topmost = closedWorld.getLubOfInstantiatedSubclasses(base); |
| 104 if (topmost == null) { | 104 if (topmost == null) { |
| 105 return new TypeMask.empty(); | 105 return new TypeMask.empty(); |
| 106 } else if (closedWorld.hasAnyStrictSubclass(topmost)) { | 106 } else if (closedWorld.hasAnyStrictSubclass(topmost)) { |
| 107 return new FlatTypeMask.subclass(topmost); | 107 return new FlatTypeMask.subclass(topmost); |
| 108 } else { | 108 } else { |
| 109 return new TypeMask.exact(topmost, closedWorld); | 109 return new TypeMask.exact(topmost, closedWorld); |
| 110 } | 110 } |
| 111 } | 111 } |
| 112 | 112 |
| 113 factory TypeMask.subtype(ClassElement base, ClosedWorld closedWorld) { | 113 factory TypeMask.subtype(Entity base, ClosedWorld closedWorld) { |
| 114 ClassElement topmost = closedWorld.getLubOfInstantiatedSubtypes(base); | 114 Entity topmost = closedWorld.getLubOfInstantiatedSubtypes(base); |
| 115 if (topmost == null) { | 115 if (topmost == null) { |
| 116 return new TypeMask.empty(); | 116 return new TypeMask.empty(); |
| 117 } | 117 } |
| 118 if (closedWorld.hasOnlySubclasses(topmost)) { | 118 if (closedWorld.hasOnlySubclasses(topmost)) { |
| 119 return new TypeMask.subclass(topmost, closedWorld); | 119 return new TypeMask.subclass(topmost, closedWorld); |
| 120 } | 120 } |
| 121 if (closedWorld.hasAnyStrictSubtype(topmost)) { | 121 if (closedWorld.hasAnyStrictSubtype(topmost)) { |
| 122 return new FlatTypeMask.subtype(topmost); | 122 return new FlatTypeMask.subtype(topmost); |
| 123 } else { | 123 } else { |
| 124 return new TypeMask.exact(topmost, closedWorld); | 124 return new TypeMask.exact(topmost, closedWorld); |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 | 127 |
| 128 const factory TypeMask.nonNullEmpty() = FlatTypeMask.nonNullEmpty; | 128 const factory TypeMask.nonNullEmpty() = FlatTypeMask.nonNullEmpty; |
| 129 | 129 |
| 130 factory TypeMask.nonNullExact(ClassElement base, ClosedWorld closedWorld) { | 130 factory TypeMask.nonNullExact(Entity base, ClosedWorld closedWorld) { |
| 131 assert(invariant(base, closedWorld.isInstantiated(base), | 131 assert(invariant(base, closedWorld.isInstantiated(base), |
| 132 message: () => "Cannot create exact type mask for uninstantiated " | 132 message: () => "Cannot create exact type mask for uninstantiated " |
| 133 "class $base.\n${closedWorld.dump(base)}")); | 133 "class $base.\n${closedWorld.dump(base)}")); |
| 134 return new FlatTypeMask.nonNullExact(base); | 134 return new FlatTypeMask.nonNullExact(base); |
| 135 } | 135 } |
| 136 | 136 |
| 137 factory TypeMask.nonNullExactOrEmpty( | 137 factory TypeMask.nonNullExactOrEmpty(Entity base, ClosedWorld closedWorld) { |
| 138 ClassElement base, ClosedWorld closedWorld) { | |
| 139 if (closedWorld.isInstantiated(base)) { | 138 if (closedWorld.isInstantiated(base)) { |
| 140 return new FlatTypeMask.nonNullExact(base); | 139 return new FlatTypeMask.nonNullExact(base); |
| 141 } | 140 } |
| 142 return const TypeMask.nonNullEmpty(); | 141 return const TypeMask.nonNullEmpty(); |
| 143 } | 142 } |
| 144 | 143 |
| 145 factory TypeMask.nonNullSubclass(ClassElement base, ClosedWorld closedWorld) { | 144 factory TypeMask.nonNullSubclass(Entity base, ClosedWorld closedWorld) { |
| 146 assert(invariant(base, closedWorld.isInstantiated(base), | 145 assert(invariant(base, closedWorld.isInstantiated(base), |
| 147 message: () => "Cannot create subclass type mask for uninstantiated " | 146 message: () => "Cannot create subclass type mask for uninstantiated " |
| 148 "class $base.\n${closedWorld.dump(base)}")); | 147 "class $base.\n${closedWorld.dump(base)}")); |
| 149 ClassElement topmost = closedWorld.getLubOfInstantiatedSubclasses(base); | 148 Entity topmost = closedWorld.getLubOfInstantiatedSubclasses(base); |
| 150 if (topmost == null) { | 149 if (topmost == null) { |
| 151 return new TypeMask.nonNullEmpty(); | 150 return new TypeMask.nonNullEmpty(); |
| 152 } else if (closedWorld.hasAnyStrictSubclass(topmost)) { | 151 } else if (closedWorld.hasAnyStrictSubclass(topmost)) { |
| 153 return new FlatTypeMask.nonNullSubclass(topmost); | 152 return new FlatTypeMask.nonNullSubclass(topmost); |
| 154 } else { | 153 } else { |
| 155 return new TypeMask.nonNullExact(topmost, closedWorld); | 154 return new TypeMask.nonNullExact(topmost, closedWorld); |
| 156 } | 155 } |
| 157 } | 156 } |
| 158 | 157 |
| 159 factory TypeMask.nonNullSubtype(ClassElement base, ClosedWorld closedWorld) { | 158 factory TypeMask.nonNullSubtype(Entity base, ClosedWorld closedWorld) { |
| 160 ClassElement topmost = closedWorld.getLubOfInstantiatedSubtypes(base); | 159 Entity topmost = closedWorld.getLubOfInstantiatedSubtypes(base); |
| 161 if (topmost == null) { | 160 if (topmost == null) { |
| 162 return new TypeMask.nonNullEmpty(); | 161 return new TypeMask.nonNullEmpty(); |
| 163 } | 162 } |
| 164 if (closedWorld.hasOnlySubclasses(topmost)) { | 163 if (closedWorld.hasOnlySubclasses(topmost)) { |
| 165 return new TypeMask.nonNullSubclass(topmost, closedWorld); | 164 return new TypeMask.nonNullSubclass(topmost, closedWorld); |
| 166 } | 165 } |
| 167 if (closedWorld.hasAnyStrictSubtype(topmost)) { | 166 if (closedWorld.hasAnyStrictSubtype(topmost)) { |
| 168 return new FlatTypeMask.nonNullSubtype(topmost); | 167 return new FlatTypeMask.nonNullSubtype(topmost); |
| 169 } else { | 168 } else { |
| 170 return new TypeMask.nonNullExact(topmost, closedWorld); | 169 return new TypeMask.nonNullExact(topmost, closedWorld); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 bool get isForwarding; | 279 bool get isForwarding; |
| 281 | 280 |
| 282 /// Returns `true` if this mask holds encodes an exact value within a type. | 281 /// Returns `true` if this mask holds encodes an exact value within a type. |
| 283 bool get isValue; | 282 bool get isValue; |
| 284 | 283 |
| 285 bool containsOnlyInt(ClosedWorld closedWorld); | 284 bool containsOnlyInt(ClosedWorld closedWorld); |
| 286 bool containsOnlyDouble(ClosedWorld closedWorld); | 285 bool containsOnlyDouble(ClosedWorld closedWorld); |
| 287 bool containsOnlyNum(ClosedWorld closedWorld); | 286 bool containsOnlyNum(ClosedWorld closedWorld); |
| 288 bool containsOnlyBool(ClosedWorld closedWorld); | 287 bool containsOnlyBool(ClosedWorld closedWorld); |
| 289 bool containsOnlyString(ClosedWorld closedWorld); | 288 bool containsOnlyString(ClosedWorld closedWorld); |
| 290 bool containsOnly(ClassElement element); | 289 bool containsOnly(Entity cls); |
| 291 | 290 |
| 292 /** | 291 /** |
| 293 * Compares two [TypeMask] objects for structural equality. | 292 * Compares two [TypeMask] objects for structural equality. |
| 294 * | 293 * |
| 295 * Note: This may differ from semantic equality in the set containment sense. | 294 * Note: This may differ from semantic equality in the set containment sense. |
| 296 * Use [containsMask] and [isInMask] for that, instead. | 295 * Use [containsMask] and [isInMask] for that, instead. |
| 297 */ | 296 */ |
| 298 bool operator ==(other); | 297 bool operator ==(other); |
| 299 | 298 |
| 300 /** | 299 /** |
| 301 * If this returns `true`, [other] is guaranteed to be a supertype of this | 300 * If this returns `true`, [other] is guaranteed to be a supertype of this |
| 302 * mask, i.e., this mask is in [other]. However, the inverse does not hold. | 301 * mask, i.e., this mask is in [other]. However, the inverse does not hold. |
| 303 * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of | 302 * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of |
| 304 * false negatives. | 303 * false negatives. |
| 305 */ | 304 */ |
| 306 bool isInMask(TypeMask other, ClosedWorld closedWorld); | 305 bool isInMask(TypeMask other, ClosedWorld closedWorld); |
| 307 | 306 |
| 308 /** | 307 /** |
| 309 * If this returns `true`, [other] is guaranteed to be a subtype of this mask, | 308 * If this returns `true`, [other] is guaranteed to be a subtype of this mask, |
| 310 * i.e., this mask contains [other]. However, the inverse does not hold. | 309 * i.e., this mask contains [other]. However, the inverse does not hold. |
| 311 * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of | 310 * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of |
| 312 * false negatives. | 311 * false negatives. |
| 313 */ | 312 */ |
| 314 bool containsMask(TypeMask other, ClosedWorld closedWorld); | 313 bool containsMask(TypeMask other, ClosedWorld closedWorld); |
| 315 | 314 |
| 316 /** | 315 /** |
| 317 * Returns whether this type mask is an instance of [cls]. | 316 * Returns whether this type mask is an instance of [cls]. |
| 318 */ | 317 */ |
| 319 bool satisfies(ClassElement cls, ClosedWorld closedWorld); | 318 bool satisfies(Entity cls, ClosedWorld closedWorld); |
| 320 | 319 |
| 321 /** | 320 /** |
| 322 * Returns whether or not this type mask contains the given type. | 321 * Returns whether or not this type mask contains the given class [cls]. |
| 323 */ | 322 */ |
| 324 bool contains(ClassElement type, ClosedWorld closedWorld); | 323 bool contains(Entity cls, ClosedWorld closedWorld); |
| 325 | 324 |
| 326 /** | 325 /** |
| 327 * Returns whether or not this type mask contains all types. | 326 * Returns whether or not this type mask contains all types. |
| 328 */ | 327 */ |
| 329 bool containsAll(ClosedWorld closedWorld); | 328 bool containsAll(ClosedWorld closedWorld); |
| 330 | 329 |
| 331 /** | 330 /// Returns the [Entity] if this type represents a single class, otherwise |
| 332 * Returns the [ClassElement] if this type represents a single class, | 331 /// returns `null`. This method is conservative. |
| 333 * otherwise returns `null`. This method is conservative. | 332 Entity singleClass(ClosedWorld closedWorld); |
| 334 */ | |
| 335 ClassElement singleClass(ClosedWorld closedWorld); | |
| 336 | 333 |
| 337 /** | 334 /** |
| 338 * Returns a type mask representing the union of [this] and [other]. | 335 * Returns a type mask representing the union of [this] and [other]. |
| 339 */ | 336 */ |
| 340 TypeMask union(TypeMask other, ClosedWorld closedWorld); | 337 TypeMask union(TypeMask other, ClosedWorld closedWorld); |
| 341 | 338 |
| 342 /// Returns whether the intersection of this and [other] is empty. | 339 /// Returns whether the intersection of this and [other] is empty. |
| 343 bool isDisjoint(TypeMask other, ClosedWorld closedWorld); | 340 bool isDisjoint(TypeMask other, ClosedWorld closedWorld); |
| 344 | 341 |
| 345 /** | 342 /** |
| 346 * Returns a type mask representing the intersection of [this] and [other]. | 343 * Returns a type mask representing the intersection of [this] and [other]. |
| 347 */ | 344 */ |
| 348 TypeMask intersection(TypeMask other, ClosedWorld closedWorld); | 345 TypeMask intersection(TypeMask other, ClosedWorld closedWorld); |
| 349 | 346 |
| 350 /** | 347 /** |
| 351 * Returns whether [element] is a potential target when being | 348 * Returns whether [element] is a potential target when being |
| 352 * invoked on this type mask. [selector] is used to ensure library | 349 * invoked on this type mask. [selector] is used to ensure library |
| 353 * privacy is taken into account. | 350 * privacy is taken into account. |
| 354 */ | 351 */ |
| 355 bool canHit(Element element, Selector selector, ClosedWorld closedWorld); | 352 bool canHit(Element element, Selector selector, ClosedWorld closedWorld); |
| 356 | 353 |
| 357 /** | 354 /** |
| 358 * Returns the [element] that is known to always be hit at runtime | 355 * Returns the [element] that is known to always be hit at runtime |
| 359 * on this mask. Returns null if there is none. | 356 * on this mask. Returns null if there is none. |
| 360 */ | 357 */ |
| 361 // TODO(johnniwinther): Move this method to [World]. | 358 // TODO(johnniwinther): Move this method to [World]. |
| 362 Element locateSingleElement(Selector selector, Compiler compiler); | 359 Element locateSingleElement(Selector selector, Compiler compiler); |
| 363 } | 360 } |
| OLD | NEW |