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
11 namespace v8 {
12 namespace internal {
13
14 enum ElementsKind {
15 // The "fast" kind for elements that only contain SMI values. Must be first
16 // to make it possible to efficiently check maps for this kind.
17 PACKED_SMI_ELEMENTS,
18 HOLEY_SMI_ELEMENTS,
19
20 // The "fast" kind for tagged values. Must be second to make it possible to
21 // efficiently check maps for this and the PACKED_SMI_ELEMENTS kind
22 // together at once.
23 PACKED_ELEMENTS,
24 HOLEY_ELEMENTS,
25
26 // The "fast" kind for unwrapped, non-tagged double values.
27 PACKED_DOUBLE_ELEMENTS,
28 HOLEY_DOUBLE_ELEMENTS,
29
30 // The "slow" kind.
31 DICTIONARY_ELEMENTS,
32
33 // Elements kind of the "arguments" object (only in sloppy mode).
34 FAST_SLOPPY_ARGUMENTS_ELEMENTS,
35 SLOW_SLOPPY_ARGUMENTS_ELEMENTS,
36
37 // For string wrapper objects ("new String('...')"), the string's characters
38 // are overlaid onto a regular elements backing store.
39 FAST_STRING_WRAPPER_ELEMENTS,
40 SLOW_STRING_WRAPPER_ELEMENTS,
41
42 // Fixed typed arrays.
43 UINT8_ELEMENTS,
44 INT8_ELEMENTS,
45 UINT16_ELEMENTS,
46 INT16_ELEMENTS,
47 UINT32_ELEMENTS,
48 INT32_ELEMENTS,
49 FLOAT32_ELEMENTS,
50 FLOAT64_ELEMENTS,
51 UINT8_CLAMPED_ELEMENTS,
52 BIGUINT64_ELEMENTS,
53 BIGINT64_ELEMENTS,
54
55 // Sentinel ElementsKind for objects with no elements.
56 NO_ELEMENTS,
57
58 // Derived constants from ElementsKind.
59 FIRST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS,
60 LAST_ELEMENTS_KIND = BIGINT64_ELEMENTS,
61 FIRST_FAST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS,
62 LAST_FAST_ELEMENTS_KIND = HOLEY_DOUBLE_ELEMENTS,
63 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS,
64 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = BIGINT64_ELEMENTS,
65 TERMINAL_FAST_ELEMENTS_KIND = HOLEY_ELEMENTS
66 };
67
68 const int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
69 const int kFastElementsKindCount =
70 LAST_FAST_ELEMENTS_KIND - FIRST_FAST_ELEMENTS_KIND + 1;
71
72 // The number to add to a packed elements kind to reach a holey elements kind
73 const int kFastElementsKindPackedToHoley =
74 HOLEY_SMI_ELEMENTS - PACKED_SMI_ELEMENTS;
75
76 int ElementsKindToShiftSize(ElementsKind elements_kind);
77 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind);
78 const char* ElementsKindToString(ElementsKind kind);
79
GetInitialFastElementsKind()80 inline ElementsKind GetInitialFastElementsKind() { return PACKED_SMI_ELEMENTS; }
81
82 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number);
83 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind);
84
85 ElementsKind GetNextTransitionElementsKind(ElementsKind elements_kind);
86
IsDictionaryElementsKind(ElementsKind kind)87 inline bool IsDictionaryElementsKind(ElementsKind kind) {
88 return kind == DICTIONARY_ELEMENTS;
89 }
90
IsSloppyArgumentsElementsKind(ElementsKind kind)91 inline bool IsSloppyArgumentsElementsKind(ElementsKind kind) {
92 return kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
93 kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
94 }
95
IsStringWrapperElementsKind(ElementsKind kind)96 inline bool IsStringWrapperElementsKind(ElementsKind kind) {
97 return kind == FAST_STRING_WRAPPER_ELEMENTS ||
98 kind == SLOW_STRING_WRAPPER_ELEMENTS;
99 }
100
IsFixedTypedArrayElementsKind(ElementsKind kind)101 inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
102 return kind >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
103 kind <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
104 }
105
IsTerminalElementsKind(ElementsKind kind)106 inline bool IsTerminalElementsKind(ElementsKind kind) {
107 return kind == TERMINAL_FAST_ELEMENTS_KIND ||
108 IsFixedTypedArrayElementsKind(kind);
109 }
110
IsFastElementsKind(ElementsKind kind)111 inline bool IsFastElementsKind(ElementsKind kind) {
112 STATIC_ASSERT(FIRST_FAST_ELEMENTS_KIND == 0);
113 return kind <= HOLEY_DOUBLE_ELEMENTS;
114 }
115
IsTransitionElementsKind(ElementsKind kind)116 inline bool IsTransitionElementsKind(ElementsKind kind) {
117 return IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind) ||
118 kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
119 kind == FAST_STRING_WRAPPER_ELEMENTS;
120 }
121
IsDoubleElementsKind(ElementsKind kind)122 inline bool IsDoubleElementsKind(ElementsKind kind) {
123 return kind == PACKED_DOUBLE_ELEMENTS || kind == HOLEY_DOUBLE_ELEMENTS;
124 }
125
126
IsFixedFloatElementsKind(ElementsKind kind)127 inline bool IsFixedFloatElementsKind(ElementsKind kind) {
128 return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
129 }
130
131
IsDoubleOrFloatElementsKind(ElementsKind kind)132 inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
133 return IsDoubleElementsKind(kind) || IsFixedFloatElementsKind(kind);
134 }
135
IsSmiOrObjectElementsKind(ElementsKind kind)136 inline bool IsSmiOrObjectElementsKind(ElementsKind kind) {
137 return kind == PACKED_SMI_ELEMENTS || kind == HOLEY_SMI_ELEMENTS ||
138 kind == PACKED_ELEMENTS || kind == HOLEY_ELEMENTS;
139 }
140
IsSmiElementsKind(ElementsKind kind)141 inline bool IsSmiElementsKind(ElementsKind kind) {
142 return kind == PACKED_SMI_ELEMENTS || kind == HOLEY_SMI_ELEMENTS;
143 }
144
IsFastNumberElementsKind(ElementsKind kind)145 inline bool IsFastNumberElementsKind(ElementsKind kind) {
146 return IsSmiElementsKind(kind) || IsDoubleElementsKind(kind);
147 }
148
IsObjectElementsKind(ElementsKind kind)149 inline bool IsObjectElementsKind(ElementsKind kind) {
150 return kind == PACKED_ELEMENTS || kind == HOLEY_ELEMENTS;
151 }
152
IsHoleyElementsKind(ElementsKind kind)153 inline bool IsHoleyElementsKind(ElementsKind kind) {
154 return kind == HOLEY_SMI_ELEMENTS || kind == HOLEY_DOUBLE_ELEMENTS ||
155 kind == HOLEY_ELEMENTS;
156 }
157
IsHoleyOrDictionaryElementsKind(ElementsKind kind)158 inline bool IsHoleyOrDictionaryElementsKind(ElementsKind kind) {
159 return IsHoleyElementsKind(kind) || kind == DICTIONARY_ELEMENTS;
160 }
161
162
IsFastPackedElementsKind(ElementsKind kind)163 inline bool IsFastPackedElementsKind(ElementsKind kind) {
164 return kind == PACKED_SMI_ELEMENTS || kind == PACKED_DOUBLE_ELEMENTS ||
165 kind == PACKED_ELEMENTS;
166 }
167
168
GetPackedElementsKind(ElementsKind holey_kind)169 inline ElementsKind GetPackedElementsKind(ElementsKind holey_kind) {
170 if (holey_kind == HOLEY_SMI_ELEMENTS) {
171 return PACKED_SMI_ELEMENTS;
172 }
173 if (holey_kind == HOLEY_DOUBLE_ELEMENTS) {
174 return PACKED_DOUBLE_ELEMENTS;
175 }
176 if (holey_kind == HOLEY_ELEMENTS) {
177 return PACKED_ELEMENTS;
178 }
179 return holey_kind;
180 }
181
182
GetHoleyElementsKind(ElementsKind packed_kind)183 inline ElementsKind GetHoleyElementsKind(ElementsKind packed_kind) {
184 if (packed_kind == PACKED_SMI_ELEMENTS) {
185 return HOLEY_SMI_ELEMENTS;
186 }
187 if (packed_kind == PACKED_DOUBLE_ELEMENTS) {
188 return HOLEY_DOUBLE_ELEMENTS;
189 }
190 if (packed_kind == PACKED_ELEMENTS) {
191 return HOLEY_ELEMENTS;
192 }
193 return packed_kind;
194 }
195
UnionElementsKindUptoPackedness(ElementsKind * a_out,ElementsKind b)196 inline bool UnionElementsKindUptoPackedness(ElementsKind* a_out,
197 ElementsKind b) {
198 // Assert that the union of two ElementKinds can be computed via std::max.
199 static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS,
200 "ElementsKind union not computable via std::max.");
201 static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS,
202 "ElementsKind union not computable via std::max.");
203 static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS,
204 "ElementsKind union not computable via std::max.");
205 ElementsKind a = *a_out;
206 switch (a) {
207 case HOLEY_SMI_ELEMENTS:
208 case PACKED_SMI_ELEMENTS:
209 if (b == PACKED_SMI_ELEMENTS || b == HOLEY_SMI_ELEMENTS) {
210 *a_out = std::max(a, b);
211 return true;
212 }
213 break;
214 case PACKED_ELEMENTS:
215 case HOLEY_ELEMENTS:
216 if (b == PACKED_ELEMENTS || b == HOLEY_ELEMENTS) {
217 *a_out = std::max(a, b);
218 return true;
219 }
220 break;
221 case PACKED_DOUBLE_ELEMENTS:
222 case HOLEY_DOUBLE_ELEMENTS:
223 if (b == PACKED_DOUBLE_ELEMENTS || b == HOLEY_DOUBLE_ELEMENTS) {
224 *a_out = std::max(a, b);
225 return true;
226 }
227 break;
228 default:
229 break;
230 }
231 return false;
232 }
233
234 bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b);
235
FastSmiToObjectElementsKind(ElementsKind from_kind)236 inline ElementsKind FastSmiToObjectElementsKind(ElementsKind from_kind) {
237 DCHECK(IsSmiElementsKind(from_kind));
238 return (from_kind == PACKED_SMI_ELEMENTS) ? PACKED_ELEMENTS : HOLEY_ELEMENTS;
239 }
240
241
IsSimpleMapChangeTransition(ElementsKind from_kind,ElementsKind to_kind)242 inline bool IsSimpleMapChangeTransition(ElementsKind from_kind,
243 ElementsKind to_kind) {
244 return (GetHoleyElementsKind(from_kind) == to_kind) ||
245 (IsSmiElementsKind(from_kind) && IsObjectElementsKind(to_kind));
246 }
247
248
249 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
250 ElementsKind to_kind);
251
252
GetMoreGeneralElementsKind(ElementsKind from_kind,ElementsKind to_kind)253 inline ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind,
254 ElementsKind to_kind) {
255 if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
256 return to_kind;
257 }
258 return from_kind;
259 }
260
261
IsTransitionableFastElementsKind(ElementsKind from_kind)262 inline bool IsTransitionableFastElementsKind(ElementsKind from_kind) {
263 return IsFastElementsKind(from_kind) &&
264 from_kind != TERMINAL_FAST_ELEMENTS_KIND;
265 }
266
ElementsKindEqual(ElementsKind a,ElementsKind b)267 inline bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; }
268
269 } // namespace internal
270 } // namespace v8
271
272 #endif // V8_ELEMENTS_KIND_H_
273