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 |