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