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