OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 part of types; | |
6 | |
7 /// A [ContainerTypeMask] is a [TypeMask] for a specific allocation | |
8 /// site of a container (currently only List) that will get specialized | |
9 /// once the [TypeGraphInferrer] phase finds an element type for it. | |
10 class ContainerTypeMask extends ForwardingTypeMask { | |
11 final TypeMask forwardTo; | |
12 | |
13 // The [Node] where this type mask was created. | |
14 final Node allocationNode; | |
15 | |
16 // The [Element] where this type mask was created. | |
17 final Element allocationElement; | |
18 | |
19 // The element type of this container. | |
20 final TypeMask elementType; | |
21 | |
22 // The length of the container. | |
23 final int length; | |
24 | |
25 ContainerTypeMask(this.forwardTo, | |
26 this.allocationNode, | |
27 this.allocationElement, | |
28 this.elementType, | |
29 this.length); | |
30 | |
31 TypeMask nullable() { | |
32 return isNullable | |
33 ? this | |
34 : new ContainerTypeMask(forwardTo.nullable(), | |
35 allocationNode, | |
36 allocationElement, | |
37 elementType, | |
38 length); | |
39 } | |
40 | |
41 TypeMask nonNullable() { | |
42 return isNullable | |
43 ? new ContainerTypeMask(forwardTo.nonNullable(), | |
44 allocationNode, | |
45 allocationElement, | |
46 elementType, | |
47 length) | |
48 : this; | |
49 } | |
50 | |
51 bool get isContainer => true; | |
52 bool get isExact => true; | |
53 | |
54 bool equalsDisregardNull(other) { | |
55 if (other is! ContainerTypeMask) return false; | |
56 return super.equalsDisregardNull(other) && | |
57 allocationNode == other.allocationNode && | |
58 elementType == other.elementType && | |
59 length == other.length; | |
60 } | |
61 | |
62 TypeMask intersection(TypeMask other, ClassWorld classWorld) { | |
63 TypeMask forwardIntersection = forwardTo.intersection(other, classWorld); | |
64 if (forwardIntersection.isEmpty) return forwardIntersection; | |
65 return forwardIntersection.isNullable | |
66 ? nullable() | |
67 : nonNullable(); | |
68 } | |
69 | |
70 TypeMask union(other, ClassWorld classWorld) { | |
71 if (this == other) { | |
72 return this; | |
73 } else if (equalsDisregardNull(other)) { | |
74 return other.isNullable ? other : this; | |
75 } else if (other.isEmpty) { | |
76 return other.isNullable ? this.nullable() : this; | |
77 } else if (other.isContainer | |
78 && elementType != null | |
79 && other.elementType != null) { | |
80 TypeMask newElementType = | |
81 elementType.union(other.elementType, classWorld); | |
82 int newLength = (length == other.length) ? length : null; | |
83 TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld); | |
84 return new ContainerTypeMask( | |
85 newForwardTo, | |
86 allocationNode == other.allocationNode ? allocationNode : null, | |
87 allocationElement == other.allocationElement ? allocationElement | |
88 : null, | |
89 newElementType, newLength); | |
90 } else { | |
91 return forwardTo.union(other, classWorld); | |
92 } | |
93 } | |
94 | |
95 bool operator==(other) => super == other; | |
96 | |
97 int get hashCode { | |
98 return computeHashCode( | |
99 allocationNode, isNullable, elementType, length, forwardTo); | |
100 } | |
101 | |
102 String toString() { | |
103 return 'Container mask: $elementType length: $length type: $forwardTo'; | |
104 } | |
105 } | |
OLD | NEW |