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