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
IsWasmArrayElementsKind(ElementsKind kind)223 inline bool IsWasmArrayElementsKind(ElementsKind kind) {
224 return kind == WASM_ARRAY_ELEMENTS;
225 }
226
IsTerminalElementsKind(ElementsKind kind)227 inline bool IsTerminalElementsKind(ElementsKind kind) {
228 return kind == TERMINAL_FAST_ELEMENTS_KIND ||
229 IsTypedArrayElementsKind(kind) ||
230 IsRabGsabTypedArrayElementsKind(kind);
231 }
232
IsFastElementsKind(ElementsKind kind)233 inline bool IsFastElementsKind(ElementsKind kind) {
234 STATIC_ASSERT(FIRST_FAST_ELEMENTS_KIND == 0);
235 return kind <= LAST_FAST_ELEMENTS_KIND;
236 }
237
IsTransitionElementsKind(ElementsKind kind)238 inline bool IsTransitionElementsKind(ElementsKind kind) {
239 return IsFastElementsKind(kind) || IsTypedArrayElementsKind(kind) ||
240 kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
241 kind == FAST_STRING_WRAPPER_ELEMENTS;
242 }
243
IsDoubleElementsKind(ElementsKind kind)244 inline bool IsDoubleElementsKind(ElementsKind kind) {
245 return base::IsInRange(kind, PACKED_DOUBLE_ELEMENTS, HOLEY_DOUBLE_ELEMENTS);
246 }
247
IsFixedFloatElementsKind(ElementsKind kind)248 inline bool IsFixedFloatElementsKind(ElementsKind kind) {
249 return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
250 }
251
IsDoubleOrFloatElementsKind(ElementsKind kind)252 inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
253 return IsDoubleElementsKind(kind) || IsFixedFloatElementsKind(kind);
254 }
255
256 // This predicate is used for disabling respective functionality in builtins.
IsAnyNonextensibleElementsKindUnchecked(ElementsKind kind)257 inline bool IsAnyNonextensibleElementsKindUnchecked(ElementsKind kind) {
258 return base::IsInRange(kind, FIRST_ANY_NONEXTENSIBLE_ELEMENTS_KIND,
259 LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND);
260 }
261
IsAnyNonextensibleElementsKind(ElementsKind kind)262 inline bool IsAnyNonextensibleElementsKind(ElementsKind kind) {
263 DCHECK_IMPLIES(IsAnyNonextensibleElementsKindUnchecked(kind),
264 FLAG_enable_sealed_frozen_elements_kind);
265 return IsAnyNonextensibleElementsKindUnchecked(kind);
266 }
267
IsNonextensibleElementsKind(ElementsKind kind)268 inline bool IsNonextensibleElementsKind(ElementsKind kind) {
269 DCHECK_IMPLIES(base::IsInRange(kind, PACKED_NONEXTENSIBLE_ELEMENTS,
270 HOLEY_NONEXTENSIBLE_ELEMENTS),
271 FLAG_enable_sealed_frozen_elements_kind);
272 return base::IsInRange(kind, PACKED_NONEXTENSIBLE_ELEMENTS,
273 HOLEY_NONEXTENSIBLE_ELEMENTS);
274 }
275
IsSealedElementsKind(ElementsKind kind)276 inline bool IsSealedElementsKind(ElementsKind kind) {
277 DCHECK_IMPLIES(
278 base::IsInRange(kind, PACKED_SEALED_ELEMENTS, HOLEY_SEALED_ELEMENTS),
279 FLAG_enable_sealed_frozen_elements_kind);
280 return base::IsInRange(kind, PACKED_SEALED_ELEMENTS, HOLEY_SEALED_ELEMENTS);
281 }
282
IsFrozenElementsKind(ElementsKind kind)283 inline bool IsFrozenElementsKind(ElementsKind kind) {
284 DCHECK_IMPLIES(
285 base::IsInRange(kind, PACKED_FROZEN_ELEMENTS, HOLEY_FROZEN_ELEMENTS),
286 FLAG_enable_sealed_frozen_elements_kind);
287 return base::IsInRange(kind, PACKED_FROZEN_ELEMENTS, HOLEY_FROZEN_ELEMENTS);
288 }
289
IsSmiOrObjectElementsKind(ElementsKind kind)290 inline bool IsSmiOrObjectElementsKind(ElementsKind kind) {
291 return base::IsInRange(kind, PACKED_SMI_ELEMENTS, HOLEY_ELEMENTS);
292 }
293
IsSmiElementsKind(ElementsKind kind)294 inline bool IsSmiElementsKind(ElementsKind kind) {
295 return base::IsInRange(kind, PACKED_SMI_ELEMENTS, HOLEY_SMI_ELEMENTS);
296 }
297
IsFastNumberElementsKind(ElementsKind kind)298 inline bool IsFastNumberElementsKind(ElementsKind kind) {
299 return IsSmiElementsKind(kind) || IsDoubleElementsKind(kind);
300 }
301
IsObjectElementsKind(ElementsKind kind)302 inline bool IsObjectElementsKind(ElementsKind kind) {
303 return base::IsInRange(kind, PACKED_ELEMENTS, HOLEY_ELEMENTS);
304 }
305
IsAnyHoleyNonextensibleElementsKind(ElementsKind kind)306 inline bool IsAnyHoleyNonextensibleElementsKind(ElementsKind kind) {
307 DCHECK_IMPLIES(kind == HOLEY_NONEXTENSIBLE_ELEMENTS ||
308 kind == HOLEY_SEALED_ELEMENTS ||
309 kind == HOLEY_FROZEN_ELEMENTS,
310 FLAG_enable_sealed_frozen_elements_kind);
311 return kind == HOLEY_NONEXTENSIBLE_ELEMENTS ||
312 kind == HOLEY_SEALED_ELEMENTS || kind == HOLEY_FROZEN_ELEMENTS;
313 }
314
IsHoleyElementsKind(ElementsKind kind)315 inline bool IsHoleyElementsKind(ElementsKind kind) {
316 return kind % 2 == 1 && kind <= HOLEY_DOUBLE_ELEMENTS;
317 }
318
IsHoleyElementsKindForRead(ElementsKind kind)319 inline bool IsHoleyElementsKindForRead(ElementsKind kind) {
320 return kind % 2 == 1 && kind <= HOLEY_FROZEN_ELEMENTS;
321 }
322
IsHoleyOrDictionaryElementsKind(ElementsKind kind)323 inline bool IsHoleyOrDictionaryElementsKind(ElementsKind kind) {
324 return IsHoleyElementsKindForRead(kind) || kind == DICTIONARY_ELEMENTS;
325 }
326
IsFastPackedElementsKind(ElementsKind kind)327 inline bool IsFastPackedElementsKind(ElementsKind kind) {
328 return kind % 2 == 0 && kind <= PACKED_DOUBLE_ELEMENTS;
329 }
330
GetPackedElementsKind(ElementsKind holey_kind)331 inline ElementsKind GetPackedElementsKind(ElementsKind holey_kind) {
332 if (holey_kind == HOLEY_SMI_ELEMENTS) {
333 return PACKED_SMI_ELEMENTS;
334 }
335 if (holey_kind == HOLEY_DOUBLE_ELEMENTS) {
336 return PACKED_DOUBLE_ELEMENTS;
337 }
338 if (holey_kind == HOLEY_ELEMENTS) {
339 return PACKED_ELEMENTS;
340 }
341 return holey_kind;
342 }
343
GetHoleyElementsKind(ElementsKind packed_kind)344 inline ElementsKind GetHoleyElementsKind(ElementsKind packed_kind) {
345 if (packed_kind == PACKED_SMI_ELEMENTS) {
346 return HOLEY_SMI_ELEMENTS;
347 }
348 if (packed_kind == PACKED_DOUBLE_ELEMENTS) {
349 return HOLEY_DOUBLE_ELEMENTS;
350 }
351 if (packed_kind == PACKED_ELEMENTS) {
352 return HOLEY_ELEMENTS;
353 }
354 if (packed_kind == PACKED_NONEXTENSIBLE_ELEMENTS) {
355 return HOLEY_NONEXTENSIBLE_ELEMENTS;
356 }
357 return packed_kind;
358 }
359
GetCorrespondingRabGsabElementsKind(ElementsKind typed_array_kind)360 inline ElementsKind GetCorrespondingRabGsabElementsKind(
361 ElementsKind typed_array_kind) {
362 DCHECK(IsTypedArrayElementsKind(typed_array_kind));
363 return ElementsKind(typed_array_kind - FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
364 FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
365 }
366
GetCorrespondingNonRabGsabElementsKind(ElementsKind typed_array_kind)367 inline ElementsKind GetCorrespondingNonRabGsabElementsKind(
368 ElementsKind typed_array_kind) {
369 DCHECK(IsRabGsabTypedArrayElementsKind(typed_array_kind));
370 return ElementsKind(typed_array_kind -
371 FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
372 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
373 }
374
UnionElementsKindUptoPackedness(ElementsKind * a_out,ElementsKind b)375 inline bool UnionElementsKindUptoPackedness(ElementsKind* a_out,
376 ElementsKind b) {
377 // Assert that the union of two ElementKinds can be computed via std::max.
378 static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS,
379 "ElementsKind union not computable via std::max.");
380 static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS,
381 "ElementsKind union not computable via std::max.");
382 static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS,
383 "ElementsKind union not computable via std::max.");
384 ElementsKind a = *a_out;
385 switch (a) {
386 case HOLEY_SMI_ELEMENTS:
387 case PACKED_SMI_ELEMENTS:
388 if (b == PACKED_SMI_ELEMENTS || b == HOLEY_SMI_ELEMENTS) {
389 *a_out = std::max(a, b);
390 return true;
391 }
392 break;
393 case PACKED_ELEMENTS:
394 case HOLEY_ELEMENTS:
395 if (b == PACKED_ELEMENTS || b == HOLEY_ELEMENTS) {
396 *a_out = std::max(a, b);
397 return true;
398 }
399 break;
400 case PACKED_DOUBLE_ELEMENTS:
401 case HOLEY_DOUBLE_ELEMENTS:
402 if (b == PACKED_DOUBLE_ELEMENTS || b == HOLEY_DOUBLE_ELEMENTS) {
403 *a_out = std::max(a, b);
404 return true;
405 }
406 break;
407 default:
408 break;
409 }
410 return false;
411 }
412
413 bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b);
414
FastSmiToObjectElementsKind(ElementsKind from_kind)415 inline ElementsKind FastSmiToObjectElementsKind(ElementsKind from_kind) {
416 DCHECK(IsSmiElementsKind(from_kind));
417 return (from_kind == PACKED_SMI_ELEMENTS) ? PACKED_ELEMENTS : HOLEY_ELEMENTS;
418 }
419
IsSimpleMapChangeTransition(ElementsKind from_kind,ElementsKind to_kind)420 inline bool IsSimpleMapChangeTransition(ElementsKind from_kind,
421 ElementsKind to_kind) {
422 return (GetHoleyElementsKind(from_kind) == to_kind) ||
423 (IsSmiElementsKind(from_kind) && IsObjectElementsKind(to_kind));
424 }
425
426 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
427 ElementsKind to_kind);
428
GetMoreGeneralElementsKind(ElementsKind from_kind,ElementsKind to_kind)429 inline ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind,
430 ElementsKind to_kind) {
431 if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
432 return to_kind;
433 }
434 return from_kind;
435 }
436
IsTransitionableFastElementsKind(ElementsKind from_kind)437 inline bool IsTransitionableFastElementsKind(ElementsKind from_kind) {
438 return IsFastElementsKind(from_kind) &&
439 from_kind != TERMINAL_FAST_ELEMENTS_KIND;
440 }
441
ElementsKindEqual(ElementsKind a,ElementsKind b)442 inline bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; }
443
444 } // namespace internal
445 } // namespace v8
446
447 #endif // V8_OBJECTS_ELEMENTS_KIND_H_
448