|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef jit_TypeRepresentationSet_h |
|
8 #define jit_TypeRepresentationSet_h |
|
9 |
|
10 #include "builtin/TypedObject.h" |
|
11 #include "jit/IonAllocPolicy.h" |
|
12 #include "js/HashTable.h" |
|
13 |
|
14 // TypeRepresentationSet stores a set of TypeRepresentation* objects, |
|
15 // representing the possible types of the binary data associated with |
|
16 // a typed object value. Often TypeRepresentationSets will be |
|
17 // singleton sets, but it is also possible to have cases where many |
|
18 // type representations flow into a single point. In such cases, the |
|
19 // various type representations may differ in their details but often |
|
20 // have a common prefix. We try to optimize this case as well. |
|
21 // |
|
22 // So, for example, consider some code like: |
|
23 // |
|
24 // var Point2Type = new StructType({x: uint8, y: uint8}); |
|
25 // var Point3Type = new StructType({x: uint8, y: uint8, z: uint8}); |
|
26 // |
|
27 // function distance2d(pnt) { |
|
28 // return Math.sqrt(pnt.x * pnt.x + pnt.y * pnt.y); |
|
29 // } |
|
30 // |
|
31 // Even if the function `distance2d()` were used with instances of |
|
32 // both Point2Type and Point3Type, we can still generate optimal code, |
|
33 // because both of those types contain fields named `x` and `y` with |
|
34 // the same types at the same offset. |
|
35 |
|
36 namespace js { |
|
37 namespace jit { |
|
38 |
|
39 class IonBuilder; |
|
40 class TypeDescrSet; |
|
41 |
|
42 class TypeDescrSetBuilder { |
|
43 private: |
|
44 Vector<TypeDescr *, 4, SystemAllocPolicy> entries_; |
|
45 bool invalid_; |
|
46 |
|
47 public: |
|
48 TypeDescrSetBuilder(); |
|
49 |
|
50 bool insert(TypeDescr *typeRepr); |
|
51 bool build(IonBuilder &builder, TypeDescrSet *out); |
|
52 }; |
|
53 |
|
54 class TypeDescrSet { |
|
55 private: |
|
56 friend struct TypeDescrSetHasher; |
|
57 friend class TypeDescrSetBuilder; |
|
58 |
|
59 size_t length_; |
|
60 TypeDescr **entries_; // Allocated using temp policy |
|
61 |
|
62 TypeDescrSet(size_t length, TypeDescr **entries); |
|
63 |
|
64 size_t length() const { |
|
65 return length_; |
|
66 } |
|
67 |
|
68 TypeDescr *get(uint32_t i) const { |
|
69 return entries_[i]; |
|
70 } |
|
71 |
|
72 template<typename T> |
|
73 bool genericType(typename T::Type *out); |
|
74 |
|
75 public: |
|
76 ////////////////////////////////////////////////////////////////////// |
|
77 // Constructors |
|
78 // |
|
79 // For more flexible constructors, see |
|
80 // TypeDescrSetBuilder above. |
|
81 |
|
82 TypeDescrSet(const TypeDescrSet &c); |
|
83 TypeDescrSet(); // empty set |
|
84 |
|
85 ////////////////////////////////////////////////////////////////////// |
|
86 // Query the set |
|
87 |
|
88 bool empty() const; |
|
89 bool allOfKind(TypeDescr::Kind kind); |
|
90 |
|
91 // Returns true only when non-empty and `kind()` is |
|
92 // `TypeDescr::Array` |
|
93 bool allOfArrayKind(); |
|
94 |
|
95 // Returns true only if (1) non-empty, (2) for all types t in this |
|
96 // set, t is sized, and (3) there is some size S such that for all |
|
97 // types t in this set, `t.size() == S`. When the above holds, |
|
98 // then also sets `*out` to S; otherwise leaves `*out` unchanged |
|
99 // and returns false. |
|
100 // |
|
101 // At the moment condition (2) trivially holds. When Bug 922115 |
|
102 // lands, some array types will be unsized. |
|
103 bool allHaveSameSize(int32_t *out); |
|
104 |
|
105 types::TemporaryTypeSet *suitableTypeSet(IonBuilder &builder, |
|
106 const Class *knownClass); |
|
107 |
|
108 ////////////////////////////////////////////////////////////////////// |
|
109 // The following operations are only valid on a non-empty set: |
|
110 |
|
111 TypeDescr::Kind kind(); |
|
112 |
|
113 // Returns the prototype that a typed object whose type is within |
|
114 // this TypeDescrSet would have. Returns `null` if this cannot be |
|
115 // predicted or instances of the type are not objects (e.g., uint8). |
|
116 JSObject *knownPrototype() const; |
|
117 |
|
118 ////////////////////////////////////////////////////////////////////// |
|
119 // Scalar operations |
|
120 // |
|
121 // Only valid when `kind() == TypeDescr::Scalar` |
|
122 |
|
123 // If all type descrs in this set have a single type, returns true |
|
124 // and sets *out. Else returns false. |
|
125 bool scalarType(ScalarTypeDescr::Type *out); |
|
126 |
|
127 ////////////////////////////////////////////////////////////////////// |
|
128 // Reference operations |
|
129 // |
|
130 // Only valid when `kind() == TypeDescr::Reference` |
|
131 |
|
132 // If all type descrs in this set have a single type, returns true |
|
133 // and sets *out. Else returns false. |
|
134 bool referenceType(ReferenceTypeDescr::Type *out); |
|
135 |
|
136 ////////////////////////////////////////////////////////////////////// |
|
137 // Reference operations |
|
138 // |
|
139 // Only valid when `kind() == TypeDescr::X4` |
|
140 |
|
141 // If all type descrs in this set have a single type, returns true |
|
142 // and sets *out. Else returns false. |
|
143 bool x4Type(X4TypeDescr::Type *out); |
|
144 |
|
145 ////////////////////////////////////////////////////////////////////// |
|
146 // SizedArray operations |
|
147 // |
|
148 // Only valid when `kind() == TypeDescr::SizedArray` |
|
149 |
|
150 // Determines whether all arrays in this set have the same, |
|
151 // statically known, array length and return that length |
|
152 // (via `*length`) if so. Otherwise returns false. |
|
153 bool hasKnownArrayLength(int32_t *length); |
|
154 |
|
155 // Returns a `TypeDescrSet` representing the element |
|
156 // types of the various array types in this set. The returned set |
|
157 // may be the empty set. |
|
158 bool arrayElementType(IonBuilder &builder, TypeDescrSet *out); |
|
159 |
|
160 ////////////////////////////////////////////////////////////////////// |
|
161 // Struct operations |
|
162 // |
|
163 // Only valid when `kind() == TypeDescr::Struct` |
|
164 |
|
165 // Searches the type in the set for a field named `id`. All |
|
166 // possible types must agree on the offset of the field within the |
|
167 // structure and the possible types of the field must be |
|
168 // compatible. If any pair of types disagree on the offset or have |
|
169 // incompatible types for the field, then `*out` will be set to |
|
170 // the empty set. |
|
171 // |
|
172 // Upon success, `out` will be set to the set of possible types of |
|
173 // the field and `offset` will be set to the field's offset within |
|
174 // the struct (measured in bytes). |
|
175 // |
|
176 // The parameter `*index` is special. If all types agree on the |
|
177 // index of the field, then `*index` is set to the field index. |
|
178 // Otherwise, it is set to SIZE_MAX. Note that two types may agree |
|
179 // on the type and offset of a field but disagree about its index, |
|
180 // e.g. the field `c` in `new StructType({a: uint8, b: uint8, c: |
|
181 // uint16})` and `new StructType({a: uint16, c: uint16})`. |
|
182 bool fieldNamed(IonBuilder &builder, |
|
183 jsid id, |
|
184 int32_t *offset, |
|
185 TypeDescrSet *out, |
|
186 size_t *index); |
|
187 }; |
|
188 |
|
189 struct TypeDescrSetHasher |
|
190 { |
|
191 typedef TypeDescrSet Lookup; |
|
192 static HashNumber hash(TypeDescrSet key); |
|
193 static bool match(TypeDescrSet key1, |
|
194 TypeDescrSet key2); |
|
195 }; |
|
196 |
|
197 typedef js::HashSet<TypeDescrSet, |
|
198 TypeDescrSetHasher, |
|
199 IonAllocPolicy> TypeDescrSetHash; |
|
200 |
|
201 } // namespace jit |
|
202 } // namespace js |
|
203 |
|
204 #endif |