Line data Source code
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 : #include "src/utils.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : // V has parameters (Type, type, TYPE, C type)
16 : #define TYPED_ARRAYS(V) \
17 : V(Uint8, uint8, UINT8, uint8_t) \
18 : V(Int8, int8, INT8, int8_t) \
19 : V(Uint16, uint16, UINT16, uint16_t) \
20 : V(Int16, int16, INT16, int16_t) \
21 : V(Uint32, uint32, UINT32, uint32_t) \
22 : V(Int32, int32, INT32, int32_t) \
23 : V(Float32, float32, FLOAT32, float) \
24 : V(Float64, float64, FLOAT64, double) \
25 : V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t) \
26 : V(BigUint64, biguint64, BIGUINT64, uint64_t) \
27 : V(BigInt64, bigint64, BIGINT64, int64_t)
28 :
29 : enum ElementsKind : uint8_t {
30 : // The "fast" kind for elements that only contain SMI values. Must be first
31 : // to make it possible to efficiently check maps for this kind.
32 : PACKED_SMI_ELEMENTS,
33 : HOLEY_SMI_ELEMENTS,
34 :
35 : // The "fast" kind for tagged values. Must be second to make it possible to
36 : // efficiently check maps for this and the PACKED_SMI_ELEMENTS kind
37 : // together at once.
38 : PACKED_ELEMENTS,
39 : HOLEY_ELEMENTS,
40 :
41 : // The "fast" kind for unwrapped, non-tagged double values.
42 : PACKED_DOUBLE_ELEMENTS,
43 : HOLEY_DOUBLE_ELEMENTS,
44 :
45 : // The sealed, frozen kind for packed elements.
46 : PACKED_SEALED_ELEMENTS,
47 : PACKED_FROZEN_ELEMENTS,
48 :
49 : // The "slow" kind.
50 : DICTIONARY_ELEMENTS,
51 :
52 : // Elements kind of the "arguments" object (only in sloppy mode).
53 : FAST_SLOPPY_ARGUMENTS_ELEMENTS,
54 : SLOW_SLOPPY_ARGUMENTS_ELEMENTS,
55 :
56 : // For string wrapper objects ("new String('...')"), the string's characters
57 : // are overlaid onto a regular elements backing store.
58 : FAST_STRING_WRAPPER_ELEMENTS,
59 : SLOW_STRING_WRAPPER_ELEMENTS,
60 :
61 : // Fixed typed arrays.
62 : #define TYPED_ARRAY_ELEMENTS_KIND(Type, type, TYPE, ctype) TYPE##_ELEMENTS,
63 : TYPED_ARRAYS(TYPED_ARRAY_ELEMENTS_KIND)
64 : #undef TYPED_ARRAY_ELEMENTS_KIND
65 :
66 : // Sentinel ElementsKind for objects with no elements.
67 : NO_ELEMENTS,
68 :
69 : // Derived constants from ElementsKind.
70 : FIRST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS,
71 : LAST_ELEMENTS_KIND = BIGINT64_ELEMENTS,
72 : FIRST_FAST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS,
73 : LAST_FAST_ELEMENTS_KIND = HOLEY_DOUBLE_ELEMENTS,
74 : FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS,
75 : LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = BIGINT64_ELEMENTS,
76 : TERMINAL_FAST_ELEMENTS_KIND = HOLEY_ELEMENTS,
77 : LAST_FROZEN_ELEMENTS_KIND = PACKED_FROZEN_ELEMENTS,
78 :
79 : // Alias for kSystemPointerSize-sized elements
80 : #ifdef V8_COMPRESS_POINTERS
81 : SYSTEM_POINTER_ELEMENTS = PACKED_DOUBLE_ELEMENTS,
82 : #else
83 : SYSTEM_POINTER_ELEMENTS = PACKED_ELEMENTS,
84 : #endif
85 : };
86 :
87 : constexpr int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
88 : constexpr int kFastElementsKindCount =
89 : LAST_FAST_ELEMENTS_KIND - FIRST_FAST_ELEMENTS_KIND + 1;
90 :
91 : // The number to add to a packed elements kind to reach a holey elements kind
92 : constexpr int kFastElementsKindPackedToHoley =
93 : HOLEY_SMI_ELEMENTS - PACKED_SMI_ELEMENTS;
94 :
95 : V8_EXPORT_PRIVATE int ElementsKindToShiftSize(ElementsKind elements_kind);
96 : V8_EXPORT_PRIVATE int ElementsKindToByteSize(ElementsKind elements_kind);
97 : int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind);
98 : const char* ElementsKindToString(ElementsKind kind);
99 :
100 : inline ElementsKind GetInitialFastElementsKind() { return PACKED_SMI_ELEMENTS; }
101 :
102 : ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number);
103 : int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind);
104 :
105 : ElementsKind GetNextTransitionElementsKind(ElementsKind elements_kind);
106 :
107 : inline bool IsDictionaryElementsKind(ElementsKind kind) {
108 : return kind == DICTIONARY_ELEMENTS;
109 : }
110 :
111 : inline bool IsSloppyArgumentsElementsKind(ElementsKind kind) {
112 : return IsInRange(kind, FAST_SLOPPY_ARGUMENTS_ELEMENTS,
113 : SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
114 : }
115 :
116 : inline bool IsStringWrapperElementsKind(ElementsKind kind) {
117 : return IsInRange(kind, FAST_STRING_WRAPPER_ELEMENTS,
118 : SLOW_STRING_WRAPPER_ELEMENTS);
119 : }
120 :
121 : inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
122 : return IsInRange(kind, FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
123 : LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
124 : }
125 :
126 : inline bool IsTerminalElementsKind(ElementsKind kind) {
127 170979 : return kind == TERMINAL_FAST_ELEMENTS_KIND ||
128 : IsFixedTypedArrayElementsKind(kind);
129 : }
130 :
131 : inline bool IsFastElementsKind(ElementsKind kind) {
132 : STATIC_ASSERT(FIRST_FAST_ELEMENTS_KIND == 0);
133 2301493 : return kind <= LAST_FAST_ELEMENTS_KIND;
134 : }
135 :
136 : inline bool IsTransitionElementsKind(ElementsKind kind) {
137 717 : return IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind) ||
138 294370 : kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
139 717 : kind == FAST_STRING_WRAPPER_ELEMENTS;
140 : }
141 :
142 : inline bool IsDoubleElementsKind(ElementsKind kind) {
143 : return IsInRange(kind, PACKED_DOUBLE_ELEMENTS, HOLEY_DOUBLE_ELEMENTS);
144 : }
145 :
146 :
147 : inline bool IsFixedFloatElementsKind(ElementsKind kind) {
148 : return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
149 : }
150 :
151 :
152 : inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
153 : return IsDoubleElementsKind(kind) || IsFixedFloatElementsKind(kind);
154 : }
155 :
156 : inline bool IsPackedFrozenOrSealedElementsKind(ElementsKind kind) {
157 : return IsInRange(kind, PACKED_SEALED_ELEMENTS, PACKED_FROZEN_ELEMENTS);
158 : }
159 :
160 : inline bool IsSealedElementsKind(ElementsKind kind) {
161 : return kind == PACKED_SEALED_ELEMENTS;
162 : }
163 :
164 : inline bool IsSmiOrObjectElementsKind(ElementsKind kind) {
165 : return kind == PACKED_SMI_ELEMENTS || kind == HOLEY_SMI_ELEMENTS ||
166 1354894 : kind == PACKED_ELEMENTS || kind == HOLEY_ELEMENTS;
167 : }
168 :
169 : inline bool IsSmiElementsKind(ElementsKind kind) {
170 : return IsInRange(kind, PACKED_SMI_ELEMENTS, HOLEY_SMI_ELEMENTS);
171 : }
172 :
173 : inline bool IsFastNumberElementsKind(ElementsKind kind) {
174 : return IsSmiElementsKind(kind) || IsDoubleElementsKind(kind);
175 : }
176 :
177 : inline bool IsObjectElementsKind(ElementsKind kind) {
178 : return IsInRange(kind, PACKED_ELEMENTS, HOLEY_ELEMENTS);
179 : }
180 :
181 : inline bool IsHoleyElementsKind(ElementsKind kind) {
182 14433477 : return kind == HOLEY_SMI_ELEMENTS || kind == HOLEY_DOUBLE_ELEMENTS ||
183 : kind == HOLEY_ELEMENTS;
184 : }
185 :
186 : inline bool IsHoleyOrDictionaryElementsKind(ElementsKind kind) {
187 5723 : return IsHoleyElementsKind(kind) || kind == DICTIONARY_ELEMENTS;
188 : }
189 :
190 :
191 : inline bool IsFastPackedElementsKind(ElementsKind kind) {
192 1526782 : return kind == PACKED_SMI_ELEMENTS || kind == PACKED_DOUBLE_ELEMENTS ||
193 : kind == PACKED_ELEMENTS;
194 : }
195 :
196 :
197 : inline ElementsKind GetPackedElementsKind(ElementsKind holey_kind) {
198 290055 : if (holey_kind == HOLEY_SMI_ELEMENTS) {
199 : return PACKED_SMI_ELEMENTS;
200 : }
201 287949 : if (holey_kind == HOLEY_DOUBLE_ELEMENTS) {
202 : return PACKED_DOUBLE_ELEMENTS;
203 : }
204 287791 : if (holey_kind == HOLEY_ELEMENTS) {
205 : return PACKED_ELEMENTS;
206 : }
207 : return holey_kind;
208 : }
209 :
210 :
211 : inline ElementsKind GetHoleyElementsKind(ElementsKind packed_kind) {
212 12433898 : if (packed_kind == PACKED_SMI_ELEMENTS) {
213 : return HOLEY_SMI_ELEMENTS;
214 : }
215 8022020 : if (packed_kind == PACKED_DOUBLE_ELEMENTS) {
216 : return HOLEY_DOUBLE_ELEMENTS;
217 : }
218 7808608 : if (packed_kind == PACKED_ELEMENTS) {
219 : return HOLEY_ELEMENTS;
220 : }
221 : return packed_kind;
222 : }
223 :
224 2154 : inline bool UnionElementsKindUptoPackedness(ElementsKind* a_out,
225 : ElementsKind b) {
226 : // Assert that the union of two ElementKinds can be computed via std::max.
227 : static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS,
228 : "ElementsKind union not computable via std::max.");
229 : static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS,
230 : "ElementsKind union not computable via std::max.");
231 : static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS,
232 : "ElementsKind union not computable via std::max.");
233 2154 : ElementsKind a = *a_out;
234 : switch (a) {
235 : case HOLEY_SMI_ELEMENTS:
236 : case PACKED_SMI_ELEMENTS:
237 1104 : if (b == PACKED_SMI_ELEMENTS || b == HOLEY_SMI_ELEMENTS) {
238 1072 : *a_out = std::max(a, b);
239 1072 : return true;
240 : }
241 : break;
242 : case PACKED_ELEMENTS:
243 : case HOLEY_ELEMENTS:
244 690 : if (b == PACKED_ELEMENTS || b == HOLEY_ELEMENTS) {
245 651 : *a_out = std::max(a, b);
246 651 : return true;
247 : }
248 : break;
249 : case PACKED_DOUBLE_ELEMENTS:
250 : case HOLEY_DOUBLE_ELEMENTS:
251 360 : if (b == PACKED_DOUBLE_ELEMENTS || b == HOLEY_DOUBLE_ELEMENTS) {
252 328 : *a_out = std::max(a, b);
253 328 : return true;
254 : }
255 : break;
256 : default:
257 : break;
258 : }
259 : return false;
260 : }
261 :
262 : bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b);
263 :
264 : inline ElementsKind FastSmiToObjectElementsKind(ElementsKind from_kind) {
265 : DCHECK(IsSmiElementsKind(from_kind));
266 : return (from_kind == PACKED_SMI_ELEMENTS) ? PACKED_ELEMENTS : HOLEY_ELEMENTS;
267 : }
268 :
269 :
270 : inline bool IsSimpleMapChangeTransition(ElementsKind from_kind,
271 : ElementsKind to_kind) {
272 3564 : return (GetHoleyElementsKind(from_kind) == to_kind) ||
273 1942 : (IsSmiElementsKind(from_kind) && IsObjectElementsKind(to_kind));
274 : }
275 :
276 :
277 : bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
278 : ElementsKind to_kind);
279 :
280 :
281 : inline ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind,
282 : ElementsKind to_kind) {
283 13244609 : if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
284 : return to_kind;
285 : }
286 : return from_kind;
287 : }
288 :
289 :
290 : inline bool IsTransitionableFastElementsKind(ElementsKind from_kind) {
291 1220224 : return IsFastElementsKind(from_kind) &&
292 : from_kind != TERMINAL_FAST_ELEMENTS_KIND;
293 : }
294 :
295 : inline bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; }
296 :
297 : } // namespace internal
298 : } // namespace v8
299 :
300 : #endif // V8_ELEMENTS_KIND_H_
|