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_OBJECTS_ELEMENTS_KIND_H_
6 #define V8_OBJECTS_ELEMENTS_KIND_H_
7
8 #include "src/base/bits.h"
9 #include "src/base/bounds.h"
10 #include "src/base/macros.h"
11 #include "src/common/checks.h"
12 #include "src/flags/flags.h"
13
14 namespace v8 {
15 namespace internal {
16
17 // V has parameters (Type, type, TYPE, C type)
18 #define TYPED_ARRAYS(V) \
19 V(Uint8, uint8, UINT8, uint8_t) \
20 V(Int8, int8, INT8, int8_t) \
21 V(Uint16, uint16, UINT16, uint16_t) \
22 V(Int16, int16, INT16, int16_t) \
23 V(Uint32, uint32, UINT32, uint32_t) \
24 V(Int32, int32, INT32, int32_t) \
25 V(Float32, float32, FLOAT32, float) \
26 V(Float64, float64, FLOAT64, double) \
27 V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t) \
28 V(BigUint64, biguint64, BIGUINT64, uint64_t) \
29 V(BigInt64, bigint64, BIGINT64, int64_t)
30
31 #define RAB_GSAB_TYPED_ARRAYS(V) \
32 V(RabGsabUint8, rab_gsab_uint8, RAB_GSAB_UINT8, uint8_t) \
33 V(RabGsabInt8, rab_gsab_int8, RAB_GSAB_INT8, int8_t) \
34 V(RabGsabUint16, rab_gsab_uint16, RAB_GSAB_UINT16, uint16_t) \
35 V(RabGsabInt16, rab_gsab_int16, RAB_GSAB_INT16, int16_t) \
36 V(RabGsabUint32, rab_gsab_uint32, RAB_GSAB_UINT32, uint32_t) \
37 V(RabGsabInt32, rab_gsab_int32, RAB_GSAB_INT32, int32_t) \
38 V(RabGsabFloat32, rab_gsab_float32, RAB_GSAB_FLOAT32, float) \
39 V(RabGsabFloat64, rab_gsab_float64, RAB_GSAB_FLOAT64, double) \
40 V(RabGsabUint8Clamped, rab_gsab_uint8_clamped, RAB_GSAB_UINT8_CLAMPED, \
41 uint8_t) \
42 V(RabGsabBigUint64, rab_gsab_biguint64, RAB_GSAB_BIGUINT64, uint64_t) \
43 V(RabGsabBigInt64, rab_gsab_bigint64, RAB_GSAB_BIGINT64, int64_t)
44
45 // The TypedArrays backed by RAB / GSAB are called Uint8Array, Uint16Array etc,
46 // and not RabGsabUint8Array, RabGsabUint16Array etc. This macro is used for
47 // generating code which refers to the TypedArray type.
48 #define RAB_GSAB_TYPED_ARRAYS_WITH_TYPED_ARRAY_TYPE(V) \
49 V(Uint8, rab_gsab_uint8, RAB_GSAB_UINT8, uint8_t) \
50 V(Int8, rab_gsab_int8, RAB_GSAB_INT8, int8_t) \
51 V(Uint16, rab_gsab_uint16, RAB_GSAB_UINT16, uint16_t) \
52 V(Int16, rab_gsab_int16, RAB_GSAB_INT16, int16_t) \
53 V(Uint32, rab_gsab_uint32, RAB_GSAB_UINT32, uint32_t) \
54 V(Int32, rab_gsab_int32, RAB_GSAB_INT32, int32_t) \
55 V(Float32, rab_gsab_float32, RAB_GSAB_FLOAT32, float) \
56 V(Float64, rab_gsab_float64, RAB_GSAB_FLOAT64, double) \
57 V(Uint8Clamped, rab_gsab_uint8_clamped, RAB_GSAB_UINT8_CLAMPED, uint8_t) \
58 V(BigUint64, rab_gsab_biguint64, RAB_GSAB_BIGUINT64, uint64_t) \
59 V(BigInt64, rab_gsab_bigint64, RAB_GSAB_BIGINT64, int64_t)
60
61 // Like RAB_GSAB_TYPED_ARRAYS but has an additional parameter for
62 // for the corresponding non-RAB/GSAB ElementsKind.
63 #define RAB_GSAB_TYPED_ARRAYS_WITH_NON_RAB_GSAB_ELEMENTS_KIND(V) \
64 V(RabGsabUint8, rab_gsab_uint8, RAB_GSAB_UINT8, uint8_t, UINT8) \
65 V(RabGsabInt8, rab_gsab_int8, RAB_GSAB_INT8, int8_t, INT8) \
66 V(RabGsabUint16, rab_gsab_uint16, RAB_GSAB_UINT16, uint16_t, UINT16) \
67 V(RabGsabInt16, rab_gsab_int16, RAB_GSAB_INT16, int16_t, INT16) \
68 V(RabGsabUint32, rab_gsab_uint32, RAB_GSAB_UINT32, uint32_t, UINT32) \
69 V(RabGsabInt32, rab_gsab_int32, RAB_GSAB_INT32, int32_t, INT32) \
70 V(RabGsabFloat32, rab_gsab_float32, RAB_GSAB_FLOAT32, float, FLOAT32) \
71 V(RabGsabFloat64, rab_gsab_float64, RAB_GSAB_FLOAT64, double, FLOAT64) \
72 V(RabGsabUint8Clamped, rab_gsab_uint8_clamped, RAB_GSAB_UINT8_CLAMPED, \
73 uint8_t, UINT8_CLAMPED) \
74 V(RabGsabBigUint64, rab_gsab_biguint64, RAB_GSAB_BIGUINT64, uint64_t, \
75 BIGUINT64) \
76 V(RabGsabBigInt64, rab_gsab_bigint64, RAB_GSAB_BIGINT64, int64_t, BIGINT64)
77
78 enum ElementsKind : uint8_t {
79 // The "fast" kind for elements that only contain SMI values. Must be first
80 // to make it possible to efficiently check maps for this kind.
81 PACKED_SMI_ELEMENTS,
82 HOLEY_SMI_ELEMENTS,
83
84 // The "fast" kind for tagged values. Must be second to make it possible to
85 // efficiently check maps for this and the PACKED_SMI_ELEMENTS kind
86 // together at once.
87 PACKED_ELEMENTS,
88 HOLEY_ELEMENTS,
89
90 // The "fast" kind for unwrapped, non-tagged double values.
91 PACKED_DOUBLE_ELEMENTS,
92 HOLEY_DOUBLE_ELEMENTS,
93
94 // The nonextensible kind for elements.
95 PACKED_NONEXTENSIBLE_ELEMENTS,
96 HOLEY_NONEXTENSIBLE_ELEMENTS,
97
98 // The sealed kind for elements.
99 PACKED_SEALED_ELEMENTS,
100 HOLEY_SEALED_ELEMENTS,
101
102 // The frozen kind for elements.
103 PACKED_FROZEN_ELEMENTS,
104 HOLEY_FROZEN_ELEMENTS,
105
106 // The "slow" kind.
107 DICTIONARY_ELEMENTS,
108
109 // Elements kind of the "arguments" object (only in sloppy mode).
110 FAST_SLOPPY_ARGUMENTS_ELEMENTS,
111 SLOW_SLOPPY_ARGUMENTS_ELEMENTS,
112
113 // For string wrapper objects ("new String('...')"), the string's characters
114 // are overlaid onto a regular elements backing store.
115 FAST_STRING_WRAPPER_ELEMENTS,
116 SLOW_STRING_WRAPPER_ELEMENTS,
117
118 // Fixed typed arrays.
119 #define TYPED_ARRAY_ELEMENTS_KIND(Type, type, TYPE, ctype) TYPE##_ELEMENTS,
120 TYPED_ARRAYS(TYPED_ARRAY_ELEMENTS_KIND)
121 RAB_GSAB_TYPED_ARRAYS(TYPED_ARRAY_ELEMENTS_KIND)
122 #undef TYPED_ARRAY_ELEMENTS_KIND
123
124 // WasmObject elements kind. The actual elements type is read from the
125 // respective WasmTypeInfo.
126 WASM_ARRAY_ELEMENTS,
127
128 // Sentinel ElementsKind for objects with no elements.
129 NO_ELEMENTS,
130
131 // Derived constants from ElementsKind.
132 FIRST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS,
133 LAST_ELEMENTS_KIND = RAB_GSAB_BIGINT64_ELEMENTS,
134 FIRST_FAST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS,
135 LAST_FAST_ELEMENTS_KIND = HOLEY_DOUBLE_ELEMENTS,
136 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS,
137 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = BIGINT64_ELEMENTS,
138 FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND = RAB_GSAB_UINT8_ELEMENTS,
139 LAST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND = RAB_GSAB_BIGINT64_ELEMENTS,
140 TERMINAL_FAST_ELEMENTS_KIND = HOLEY_ELEMENTS,
141 FIRST_ANY_NONEXTENSIBLE_ELEMENTS_KIND = PACKED_NONEXTENSIBLE_ELEMENTS,
142 LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND = HOLEY_FROZEN_ELEMENTS,
143
144 // Alias for kSystemPointerSize-sized elements
145 #ifdef V8_COMPRESS_POINTERS
146 SYSTEM_POINTER_ELEMENTS = PACKED_DOUBLE_ELEMENTS,
147 #else
148 SYSTEM_POINTER_ELEMENTS = PACKED_ELEMENTS,
149 #endif
150 };
151
152 constexpr int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
153 constexpr int kFastElementsKindCount =
154 LAST_FAST_ELEMENTS_KIND - FIRST_FAST_ELEMENTS_KIND + 1;
155
156 // The number to add to a packed elements kind to reach a holey elements kind
157 constexpr int kFastElementsKindPackedToHoley =
158 HOLEY_SMI_ELEMENTS - PACKED_SMI_ELEMENTS;
159
160 constexpr int kElementsKindBits = 6;
161 STATIC_ASSERT((1 << kElementsKindBits) > LAST_ELEMENTS_KIND);
162 STATIC_ASSERT((1 << (kElementsKindBits - 1)) <= LAST_ELEMENTS_KIND);
163
164 constexpr int kFastElementsKindBits = 3;
165 STATIC_ASSERT((1 << kFastElementsKindBits) > LAST_FAST_ELEMENTS_KIND);
166 STATIC_ASSERT((1 << (kFastElementsKindBits - 1)) <= LAST_FAST_ELEMENTS_KIND);
167
168 V8_EXPORT_PRIVATE int ElementsKindToShiftSize(ElementsKind elements_kind);
169 V8_EXPORT_PRIVATE int ElementsKindToByteSize(ElementsKind elements_kind);
170 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind);
171 const char* ElementsKindToString(ElementsKind kind);
172
GetInitialFastElementsKind()173 inline ElementsKind GetInitialFastElementsKind() { return PACKED_SMI_ELEMENTS; }
174
175 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number);
176 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind);
177
178 ElementsKind GetNextTransitionElementsKind(ElementsKind elements_kind);
179
IsDictionaryElementsKind(ElementsKind kind)180 inline bool IsDictionaryElementsKind(ElementsKind kind) {
181 return kind == DICTIONARY_ELEMENTS;
182 }
183
IsFastArgumentsElementsKind(ElementsKind kind)184 inline bool IsFastArgumentsElementsKind(ElementsKind kind) {
185 return kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
186 }
187
IsSlowArgumentsElementsKind(ElementsKind kind)188 inline bool IsSlowArgumentsElementsKind(ElementsKind kind) {
189 return kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
190 }
191
IsSloppyArgumentsElementsKind(ElementsKind kind)192 inline bool IsSloppyArgumentsElementsKind(ElementsKind kind) {
193 return base::IsInRange(kind, FAST_SLOPPY_ARGUMENTS_ELEMENTS,
194 SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
195 }
196
IsStringWrapperElementsKind(ElementsKind kind)197 inline bool IsStringWrapperElementsKind(ElementsKind kind) {
198 return base::IsInRange(kind, FAST_STRING_WRAPPER_ELEMENTS,
199 SLOW_STRING_WRAPPER_ELEMENTS);
200 }
201
IsTypedArrayElementsKind(ElementsKind kind)202 inline bool IsTypedArrayElementsKind(ElementsKind kind) {
203 return base::IsInRange(kind, FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
204 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
205 }
206
IsRabGsabTypedArrayElementsKind(ElementsKind kind)207 inline bool IsRabGsabTypedArrayElementsKind(ElementsKind kind) {
208 return base::IsInRange(kind, FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
209 LAST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
210 }
211
IsTypedArrayOrRabGsabTypedArrayElementsKind(ElementsKind kind)212 inline bool IsTypedArrayOrRabGsabTypedArrayElementsKind(ElementsKind kind) {
213 return base::IsInRange(kind, FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
214 LAST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
215 }
216
IsBigIntTypedArrayElementsKind(ElementsKind kind)217 inline bool IsBigIntTypedArrayElementsKind(ElementsKind kind) {
218 return kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS ||
219 kind == RAB_GSAB_BIGINT64_ELEMENTS ||
220 kind == RAB_GSAB_BIGUINT64_ELEMENTS;
221 }
222
IsFloatTypedArrayElementsKind(ElementsKind kind)223 inline bool IsFloatTypedArrayElementsKind(ElementsKind kind) {
224 return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS ||
225 kind == RAB_GSAB_FLOAT32_ELEMENTS || kind == RAB_GSAB_FLOAT64_ELEMENTS;
226 }
227
IsWasmArrayElementsKind(ElementsKind kind)228 inline bool IsWasmArrayElementsKind(ElementsKind kind) {
229 return kind == WASM_ARRAY_ELEMENTS;
230 }
231
IsTerminalElementsKind(ElementsKind kind)232 inline bool IsTerminalElementsKind(ElementsKind kind) {
233 return kind == TERMINAL_FAST_ELEMENTS_KIND ||
234 IsTypedArrayElementsKind(kind) ||
235 IsRabGsabTypedArrayElementsKind(kind);
236 }
237
IsFastElementsKind(ElementsKind kind)238 inline bool IsFastElementsKind(ElementsKind kind) {
239 STATIC_ASSERT(FIRST_FAST_ELEMENTS_KIND == 0);
240 return kind <= LAST_FAST_ELEMENTS_KIND;
241 }
242
IsTransitionElementsKind(ElementsKind kind)243 inline bool IsTransitionElementsKind(ElementsKind kind) {
244 return IsFastElementsKind(kind) || IsTypedArrayElementsKind(kind) ||
245 kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
246 kind == FAST_STRING_WRAPPER_ELEMENTS;
247 }
248
IsDoubleElementsKind(ElementsKind kind)249 inline bool IsDoubleElementsKind(ElementsKind kind) {
250 return base::IsInRange(kind, PACKED_DOUBLE_ELEMENTS, HOLEY_DOUBLE_ELEMENTS);
251 }
252
IsFixedFloatElementsKind(ElementsKind kind)253 inline bool IsFixedFloatElementsKind(ElementsKind kind) {
254 return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
255 }
256
IsDoubleOrFloatElementsKind(ElementsKind kind)257 inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
258 return IsDoubleElementsKind(kind) || IsFixedFloatElementsKind(kind);
259 }
260
261 // This predicate is used for disabling respective functionality in builtins.
IsAnyNonextensibleElementsKindUnchecked(ElementsKind kind)262 inline bool IsAnyNonextensibleElementsKindUnchecked(ElementsKind kind) {
263 return base::IsInRange(kind, FIRST_ANY_NONEXTENSIBLE_ELEMENTS_KIND,
264 LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND);
265 }
266
IsAnyNonextensibleElementsKind(ElementsKind kind)267 inline bool IsAnyNonextensibleElementsKind(ElementsKind kind) {
268 DCHECK_IMPLIES(IsAnyNonextensibleElementsKindUnchecked(kind),
269 FLAG_enable_sealed_frozen_elements_kind);
270 return IsAnyNonextensibleElementsKindUnchecked(kind);
271 }
272
IsNonextensibleElementsKind(ElementsKind kind)273 inline bool IsNonextensibleElementsKind(ElementsKind kind) {
274 DCHECK_IMPLIES(base::IsInRange(kind, PACKED_NONEXTENSIBLE_ELEMENTS,
275 HOLEY_NONEXTENSIBLE_ELEMENTS),
276 FLAG_enable_sealed_frozen_elements_kind);
277 return base::IsInRange(kind, PACKED_NONEXTENSIBLE_ELEMENTS,
278 HOLEY_NONEXTENSIBLE_ELEMENTS);
279 }
280
IsSealedElementsKind(ElementsKind kind)281 inline bool IsSealedElementsKind(ElementsKind kind) {
282 DCHECK_IMPLIES(
283 base::IsInRange(kind, PACKED_SEALED_ELEMENTS, HOLEY_SEALED_ELEMENTS),
284 FLAG_enable_sealed_frozen_elements_kind);
285 return base::IsInRange(kind, PACKED_SEALED_ELEMENTS, HOLEY_SEALED_ELEMENTS);
286 }
287
IsFrozenElementsKind(ElementsKind kind)288 inline bool IsFrozenElementsKind(ElementsKind kind) {
289 DCHECK_IMPLIES(
290 base::IsInRange(kind, PACKED_FROZEN_ELEMENTS, HOLEY_FROZEN_ELEMENTS),
291 FLAG_enable_sealed_frozen_elements_kind);
292 return base::IsInRange(kind, PACKED_FROZEN_ELEMENTS, HOLEY_FROZEN_ELEMENTS);
293 }
294
IsSmiOrObjectElementsKind(ElementsKind kind)295 inline bool IsSmiOrObjectElementsKind(ElementsKind kind) {
296 return base::IsInRange(kind, PACKED_SMI_ELEMENTS, HOLEY_ELEMENTS);
297 }
298
IsSmiElementsKind(ElementsKind kind)299 inline bool IsSmiElementsKind(ElementsKind kind) {
300 return base::IsInRange(kind, PACKED_SMI_ELEMENTS, HOLEY_SMI_ELEMENTS);
301 }
302
IsFastNumberElementsKind(ElementsKind kind)303 inline bool IsFastNumberElementsKind(ElementsKind kind) {
304 return IsSmiElementsKind(kind) || IsDoubleElementsKind(kind);
305 }
306
IsObjectElementsKind(ElementsKind kind)307 inline bool IsObjectElementsKind(ElementsKind kind) {
308 return base::IsInRange(kind, PACKED_ELEMENTS, HOLEY_ELEMENTS);
309 }
310
IsAnyHoleyNonextensibleElementsKind(ElementsKind kind)311 inline bool IsAnyHoleyNonextensibleElementsKind(ElementsKind kind) {
312 DCHECK_IMPLIES(kind == HOLEY_NONEXTENSIBLE_ELEMENTS ||
313 kind == HOLEY_SEALED_ELEMENTS ||
314 kind == HOLEY_FROZEN_ELEMENTS,
315 FLAG_enable_sealed_frozen_elements_kind);
316 return kind == HOLEY_NONEXTENSIBLE_ELEMENTS ||
317 kind == HOLEY_SEALED_ELEMENTS || kind == HOLEY_FROZEN_ELEMENTS;
318 }
319
IsHoleyElementsKind(ElementsKind kind)320 inline bool IsHoleyElementsKind(ElementsKind kind) {
321 return kind % 2 == 1 && kind <= HOLEY_DOUBLE_ELEMENTS;
322 }
323
IsHoleyElementsKindForRead(ElementsKind kind)324 inline bool IsHoleyElementsKindForRead(ElementsKind kind) {
325 return kind % 2 == 1 && kind <= HOLEY_FROZEN_ELEMENTS;
326 }
327
IsHoleyOrDictionaryElementsKind(ElementsKind kind)328 inline bool IsHoleyOrDictionaryElementsKind(ElementsKind kind) {
329 return IsHoleyElementsKindForRead(kind) || kind == DICTIONARY_ELEMENTS;
330 }
331
IsFastPackedElementsKind(ElementsKind kind)332 inline bool IsFastPackedElementsKind(ElementsKind kind) {
333 return kind % 2 == 0 && kind <= PACKED_DOUBLE_ELEMENTS;
334 }
335
GetPackedElementsKind(ElementsKind holey_kind)336 inline ElementsKind GetPackedElementsKind(ElementsKind holey_kind) {
337 if (holey_kind == HOLEY_SMI_ELEMENTS) {
338 return PACKED_SMI_ELEMENTS;
339 }
340 if (holey_kind == HOLEY_DOUBLE_ELEMENTS) {
341 return PACKED_DOUBLE_ELEMENTS;
342 }
343 if (holey_kind == HOLEY_ELEMENTS) {
344 return PACKED_ELEMENTS;
345 }
346 return holey_kind;
347 }
348
GetHoleyElementsKind(ElementsKind packed_kind)349 inline ElementsKind GetHoleyElementsKind(ElementsKind packed_kind) {
350 if (packed_kind == PACKED_SMI_ELEMENTS) {
351 return HOLEY_SMI_ELEMENTS;
352 }
353 if (packed_kind == PACKED_DOUBLE_ELEMENTS) {
354 return HOLEY_DOUBLE_ELEMENTS;
355 }
356 if (packed_kind == PACKED_ELEMENTS) {
357 return HOLEY_ELEMENTS;
358 }
359 if (packed_kind == PACKED_NONEXTENSIBLE_ELEMENTS) {
360 return HOLEY_NONEXTENSIBLE_ELEMENTS;
361 }
362 return packed_kind;
363 }
364
GetCorrespondingRabGsabElementsKind(ElementsKind typed_array_kind)365 inline ElementsKind GetCorrespondingRabGsabElementsKind(
366 ElementsKind typed_array_kind) {
367 DCHECK(IsTypedArrayElementsKind(typed_array_kind));
368 return ElementsKind(typed_array_kind - FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
369 FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
370 }
371
GetCorrespondingNonRabGsabElementsKind(ElementsKind typed_array_kind)372 inline ElementsKind GetCorrespondingNonRabGsabElementsKind(
373 ElementsKind typed_array_kind) {
374 DCHECK(IsRabGsabTypedArrayElementsKind(typed_array_kind));
375 return ElementsKind(typed_array_kind -
376 FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
377 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
378 }
379
UnionElementsKindUptoPackedness(ElementsKind * a_out,ElementsKind b)380 inline bool UnionElementsKindUptoPackedness(ElementsKind* a_out,
381 ElementsKind b) {
382 // Assert that the union of two ElementKinds can be computed via std::max.
383 static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS,
384 "ElementsKind union not computable via std::max.");
385 static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS,
386 "ElementsKind union not computable via std::max.");
387 static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS,
388 "ElementsKind union not computable via std::max.");
389 ElementsKind a = *a_out;
390 switch (a) {
391 case HOLEY_SMI_ELEMENTS:
392 case PACKED_SMI_ELEMENTS:
393 if (b == PACKED_SMI_ELEMENTS || b == HOLEY_SMI_ELEMENTS) {
394 *a_out = std::max(a, b);
395 return true;
396 }
397 break;
398 case PACKED_ELEMENTS:
399 case HOLEY_ELEMENTS:
400 if (b == PACKED_ELEMENTS || b == HOLEY_ELEMENTS) {
401 *a_out = std::max(a, b);
402 return true;
403 }
404 break;
405 case PACKED_DOUBLE_ELEMENTS:
406 case HOLEY_DOUBLE_ELEMENTS:
407 if (b == PACKED_DOUBLE_ELEMENTS || b == HOLEY_DOUBLE_ELEMENTS) {
408 *a_out = std::max(a, b);
409 return true;
410 }
411 break;
412 default:
413 break;
414 }
415 return false;
416 }
417
418 bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b);
419
FastSmiToObjectElementsKind(ElementsKind from_kind)420 inline ElementsKind FastSmiToObjectElementsKind(ElementsKind from_kind) {
421 DCHECK(IsSmiElementsKind(from_kind));
422 return (from_kind == PACKED_SMI_ELEMENTS) ? PACKED_ELEMENTS : HOLEY_ELEMENTS;
423 }
424
IsSimpleMapChangeTransition(ElementsKind from_kind,ElementsKind to_kind)425 inline bool IsSimpleMapChangeTransition(ElementsKind from_kind,
426 ElementsKind to_kind) {
427 return (GetHoleyElementsKind(from_kind) == to_kind) ||
428 (IsSmiElementsKind(from_kind) && IsObjectElementsKind(to_kind));
429 }
430
431 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
432 ElementsKind to_kind);
433
GetMoreGeneralElementsKind(ElementsKind from_kind,ElementsKind to_kind)434 inline ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind,
435 ElementsKind to_kind) {
436 if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
437 return to_kind;
438 }
439 return from_kind;
440 }
441
IsTransitionableFastElementsKind(ElementsKind from_kind)442 inline bool IsTransitionableFastElementsKind(ElementsKind from_kind) {
443 return IsFastElementsKind(from_kind) &&
444 from_kind != TERMINAL_FAST_ELEMENTS_KIND;
445 }
446
ElementsKindEqual(ElementsKind a,ElementsKind b)447 inline bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; }
448
449 } // namespace internal
450 } // namespace v8
451
452 #endif // V8_OBJECTS_ELEMENTS_KIND_H_
453