• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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