1 | // Copyright 2012 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef V8_ELEMENTS_KIND_H_ |
6 | #define V8_ELEMENTS_KIND_H_ |
7 | |
8 | #include "src/base/macros.h" |
9 | #include "src/checks.h" |
10 | #include "src/utils.h" |
11 | |
12 | namespace v8 { |
13 | namespace internal { |
14 | |
15 | // V has parameters (Type, type, TYPE, C type) |
16 | #define TYPED_ARRAYS(V) \ |
17 | V(Uint8, uint8, UINT8, uint8_t) \ |
18 | V(Int8, int8, INT8, int8_t) \ |
19 | V(Uint16, uint16, UINT16, uint16_t) \ |
20 | V(Int16, int16, INT16, int16_t) \ |
21 | V(Uint32, uint32, UINT32, uint32_t) \ |
22 | V(Int32, int32, INT32, int32_t) \ |
23 | V(Float32, float32, FLOAT32, float) \ |
24 | V(Float64, float64, FLOAT64, double) \ |
25 | V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t) \ |
26 | V(BigUint64, biguint64, BIGUINT64, uint64_t) \ |
27 | V(BigInt64, bigint64, BIGINT64, int64_t) |
28 | |
29 | enum ElementsKind : uint8_t { |
30 | // The "fast" kind for elements that only contain SMI values. Must be first |
31 | // to make it possible to efficiently check maps for this kind. |
32 | PACKED_SMI_ELEMENTS, |
33 | HOLEY_SMI_ELEMENTS, |
34 | |
35 | // The "fast" kind for tagged values. Must be second to make it possible to |
36 | // efficiently check maps for this and the PACKED_SMI_ELEMENTS kind |
37 | // together at once. |
38 | PACKED_ELEMENTS, |
39 | HOLEY_ELEMENTS, |
40 | |
41 | // The "fast" kind for unwrapped, non-tagged double values. |
42 | PACKED_DOUBLE_ELEMENTS, |
43 | HOLEY_DOUBLE_ELEMENTS, |
44 | |
45 | // The sealed, frozen kind for packed elements. |
46 | PACKED_SEALED_ELEMENTS, |
47 | PACKED_FROZEN_ELEMENTS, |
48 | |
49 | // The "slow" kind. |
50 | DICTIONARY_ELEMENTS, |
51 | |
52 | // Elements kind of the "arguments" object (only in sloppy mode). |
53 | FAST_SLOPPY_ARGUMENTS_ELEMENTS, |
54 | SLOW_SLOPPY_ARGUMENTS_ELEMENTS, |
55 | |
56 | // For string wrapper objects ("new String('...')"), the string's characters |
57 | // are overlaid onto a regular elements backing store. |
58 | FAST_STRING_WRAPPER_ELEMENTS, |
59 | SLOW_STRING_WRAPPER_ELEMENTS, |
60 | |
61 | // Fixed typed arrays. |
62 | #define TYPED_ARRAY_ELEMENTS_KIND(Type, type, TYPE, ctype) TYPE##_ELEMENTS, |
63 | TYPED_ARRAYS(TYPED_ARRAY_ELEMENTS_KIND) |
64 | #undef TYPED_ARRAY_ELEMENTS_KIND |
65 | |
66 | // Sentinel ElementsKind for objects with no elements. |
67 | NO_ELEMENTS, |
68 | |
69 | // Derived constants from ElementsKind. |
70 | FIRST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS, |
71 | LAST_ELEMENTS_KIND = BIGINT64_ELEMENTS, |
72 | FIRST_FAST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS, |
73 | LAST_FAST_ELEMENTS_KIND = HOLEY_DOUBLE_ELEMENTS, |
74 | FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS, |
75 | LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = BIGINT64_ELEMENTS, |
76 | TERMINAL_FAST_ELEMENTS_KIND = HOLEY_ELEMENTS, |
77 | LAST_FROZEN_ELEMENTS_KIND = PACKED_FROZEN_ELEMENTS, |
78 | |
79 | // Alias for kSystemPointerSize-sized elements |
80 | #ifdef V8_COMPRESS_POINTERS |
81 | SYSTEM_POINTER_ELEMENTS = PACKED_DOUBLE_ELEMENTS, |
82 | #else |
83 | SYSTEM_POINTER_ELEMENTS = PACKED_ELEMENTS, |
84 | #endif |
85 | }; |
86 | |
87 | constexpr int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1; |
88 | constexpr int kFastElementsKindCount = |
89 | LAST_FAST_ELEMENTS_KIND - FIRST_FAST_ELEMENTS_KIND + 1; |
90 | |
91 | // The number to add to a packed elements kind to reach a holey elements kind |
92 | constexpr int kFastElementsKindPackedToHoley = |
93 | HOLEY_SMI_ELEMENTS - PACKED_SMI_ELEMENTS; |
94 | |
95 | V8_EXPORT_PRIVATE int ElementsKindToShiftSize(ElementsKind elements_kind); |
96 | V8_EXPORT_PRIVATE int ElementsKindToByteSize(ElementsKind elements_kind); |
97 | int (ElementsKind elements_kind); |
98 | const char* ElementsKindToString(ElementsKind kind); |
99 | |
100 | inline ElementsKind GetInitialFastElementsKind() { return PACKED_SMI_ELEMENTS; } |
101 | |
102 | ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number); |
103 | int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind); |
104 | |
105 | ElementsKind GetNextTransitionElementsKind(ElementsKind elements_kind); |
106 | |
107 | inline bool IsDictionaryElementsKind(ElementsKind kind) { |
108 | return kind == DICTIONARY_ELEMENTS; |
109 | } |
110 | |
111 | inline bool IsSloppyArgumentsElementsKind(ElementsKind kind) { |
112 | return IsInRange(kind, FAST_SLOPPY_ARGUMENTS_ELEMENTS, |
113 | SLOW_SLOPPY_ARGUMENTS_ELEMENTS); |
114 | } |
115 | |
116 | inline bool IsStringWrapperElementsKind(ElementsKind kind) { |
117 | return IsInRange(kind, FAST_STRING_WRAPPER_ELEMENTS, |
118 | SLOW_STRING_WRAPPER_ELEMENTS); |
119 | } |
120 | |
121 | inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) { |
122 | return IsInRange(kind, FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND, |
123 | LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND); |
124 | } |
125 | |
126 | inline bool IsTerminalElementsKind(ElementsKind kind) { |
127 | return kind == TERMINAL_FAST_ELEMENTS_KIND || |
128 | IsFixedTypedArrayElementsKind(kind); |
129 | } |
130 | |
131 | inline bool IsFastElementsKind(ElementsKind kind) { |
132 | STATIC_ASSERT(FIRST_FAST_ELEMENTS_KIND == 0); |
133 | return kind <= LAST_FAST_ELEMENTS_KIND; |
134 | } |
135 | |
136 | inline bool IsTransitionElementsKind(ElementsKind kind) { |
137 | return IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind) || |
138 | kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS || |
139 | kind == FAST_STRING_WRAPPER_ELEMENTS; |
140 | } |
141 | |
142 | inline bool IsDoubleElementsKind(ElementsKind kind) { |
143 | return IsInRange(kind, PACKED_DOUBLE_ELEMENTS, HOLEY_DOUBLE_ELEMENTS); |
144 | } |
145 | |
146 | |
147 | inline bool IsFixedFloatElementsKind(ElementsKind kind) { |
148 | return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS; |
149 | } |
150 | |
151 | |
152 | inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) { |
153 | return IsDoubleElementsKind(kind) || IsFixedFloatElementsKind(kind); |
154 | } |
155 | |
156 | inline bool IsFrozenOrSealedElementsKind(ElementsKind kind) { |
157 | return IsInRange(kind, PACKED_SEALED_ELEMENTS, PACKED_FROZEN_ELEMENTS); |
158 | } |
159 | |
160 | inline bool IsSealedElementsKind(ElementsKind kind) { |
161 | return kind == PACKED_SEALED_ELEMENTS; |
162 | } |
163 | |
164 | inline bool IsSmiOrObjectElementsKind(ElementsKind kind) { |
165 | return kind == PACKED_SMI_ELEMENTS || kind == HOLEY_SMI_ELEMENTS || |
166 | kind == PACKED_ELEMENTS || kind == HOLEY_ELEMENTS; |
167 | } |
168 | |
169 | inline bool IsSmiElementsKind(ElementsKind kind) { |
170 | return IsInRange(kind, PACKED_SMI_ELEMENTS, HOLEY_SMI_ELEMENTS); |
171 | } |
172 | |
173 | inline bool IsFastNumberElementsKind(ElementsKind kind) { |
174 | return IsSmiElementsKind(kind) || IsDoubleElementsKind(kind); |
175 | } |
176 | |
177 | inline bool IsObjectElementsKind(ElementsKind kind) { |
178 | return IsInRange(kind, PACKED_ELEMENTS, HOLEY_ELEMENTS); |
179 | } |
180 | |
181 | inline bool IsHoleyElementsKind(ElementsKind kind) { |
182 | return kind == HOLEY_SMI_ELEMENTS || kind == HOLEY_DOUBLE_ELEMENTS || |
183 | kind == HOLEY_ELEMENTS; |
184 | } |
185 | |
186 | inline bool IsHoleyOrDictionaryElementsKind(ElementsKind kind) { |
187 | return IsHoleyElementsKind(kind) || kind == DICTIONARY_ELEMENTS; |
188 | } |
189 | |
190 | |
191 | inline bool IsFastPackedElementsKind(ElementsKind kind) { |
192 | return kind == PACKED_SMI_ELEMENTS || kind == PACKED_DOUBLE_ELEMENTS || |
193 | kind == PACKED_ELEMENTS; |
194 | } |
195 | |
196 | |
197 | inline ElementsKind GetPackedElementsKind(ElementsKind holey_kind) { |
198 | if (holey_kind == HOLEY_SMI_ELEMENTS) { |
199 | return PACKED_SMI_ELEMENTS; |
200 | } |
201 | if (holey_kind == HOLEY_DOUBLE_ELEMENTS) { |
202 | return PACKED_DOUBLE_ELEMENTS; |
203 | } |
204 | if (holey_kind == HOLEY_ELEMENTS) { |
205 | return PACKED_ELEMENTS; |
206 | } |
207 | return holey_kind; |
208 | } |
209 | |
210 | |
211 | inline ElementsKind GetHoleyElementsKind(ElementsKind packed_kind) { |
212 | if (packed_kind == PACKED_SMI_ELEMENTS) { |
213 | return HOLEY_SMI_ELEMENTS; |
214 | } |
215 | if (packed_kind == PACKED_DOUBLE_ELEMENTS) { |
216 | return HOLEY_DOUBLE_ELEMENTS; |
217 | } |
218 | if (packed_kind == PACKED_ELEMENTS) { |
219 | return HOLEY_ELEMENTS; |
220 | } |
221 | return packed_kind; |
222 | } |
223 | |
224 | inline bool UnionElementsKindUptoPackedness(ElementsKind* a_out, |
225 | ElementsKind b) { |
226 | // Assert that the union of two ElementKinds can be computed via std::max. |
227 | static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS, |
228 | "ElementsKind union not computable via std::max." ); |
229 | static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS, |
230 | "ElementsKind union not computable via std::max." ); |
231 | static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS, |
232 | "ElementsKind union not computable via std::max." ); |
233 | ElementsKind a = *a_out; |
234 | switch (a) { |
235 | case HOLEY_SMI_ELEMENTS: |
236 | case PACKED_SMI_ELEMENTS: |
237 | if (b == PACKED_SMI_ELEMENTS || b == HOLEY_SMI_ELEMENTS) { |
238 | *a_out = std::max(a, b); |
239 | return true; |
240 | } |
241 | break; |
242 | case PACKED_ELEMENTS: |
243 | case HOLEY_ELEMENTS: |
244 | if (b == PACKED_ELEMENTS || b == HOLEY_ELEMENTS) { |
245 | *a_out = std::max(a, b); |
246 | return true; |
247 | } |
248 | break; |
249 | case PACKED_DOUBLE_ELEMENTS: |
250 | case HOLEY_DOUBLE_ELEMENTS: |
251 | if (b == PACKED_DOUBLE_ELEMENTS || b == HOLEY_DOUBLE_ELEMENTS) { |
252 | *a_out = std::max(a, b); |
253 | return true; |
254 | } |
255 | break; |
256 | default: |
257 | break; |
258 | } |
259 | return false; |
260 | } |
261 | |
262 | bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b); |
263 | |
264 | inline ElementsKind FastSmiToObjectElementsKind(ElementsKind from_kind) { |
265 | DCHECK(IsSmiElementsKind(from_kind)); |
266 | return (from_kind == PACKED_SMI_ELEMENTS) ? PACKED_ELEMENTS : HOLEY_ELEMENTS; |
267 | } |
268 | |
269 | |
270 | inline bool IsSimpleMapChangeTransition(ElementsKind from_kind, |
271 | ElementsKind to_kind) { |
272 | return (GetHoleyElementsKind(from_kind) == to_kind) || |
273 | (IsSmiElementsKind(from_kind) && IsObjectElementsKind(to_kind)); |
274 | } |
275 | |
276 | |
277 | bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, |
278 | ElementsKind to_kind); |
279 | |
280 | |
281 | inline ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind, |
282 | ElementsKind to_kind) { |
283 | if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
284 | return to_kind; |
285 | } |
286 | return from_kind; |
287 | } |
288 | |
289 | |
290 | inline bool IsTransitionableFastElementsKind(ElementsKind from_kind) { |
291 | return IsFastElementsKind(from_kind) && |
292 | from_kind != TERMINAL_FAST_ELEMENTS_KIND; |
293 | } |
294 | |
295 | inline bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; } |
296 | |
297 | } // namespace internal |
298 | } // namespace v8 |
299 | |
300 | #endif // V8_ELEMENTS_KIND_H_ |
301 | |