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 #include "src/objects/elements-kind.h"
6
7 #include "src/base/lazy-instance.h"
8 #include "src/objects/elements.h"
9 #include "src/objects/objects-inl.h"
10 #include "src/objects/objects.h"
11
12 namespace v8 {
13 namespace internal {
14
ElementsKindToShiftSize(ElementsKind elements_kind)15 int ElementsKindToShiftSize(ElementsKind elements_kind) {
16 switch (elements_kind) {
17 case UINT8_ELEMENTS:
18 case INT8_ELEMENTS:
19 case UINT8_CLAMPED_ELEMENTS:
20 case RAB_GSAB_UINT8_ELEMENTS:
21 case RAB_GSAB_INT8_ELEMENTS:
22 case RAB_GSAB_UINT8_CLAMPED_ELEMENTS:
23 return 0;
24 case UINT16_ELEMENTS:
25 case INT16_ELEMENTS:
26 case RAB_GSAB_UINT16_ELEMENTS:
27 case RAB_GSAB_INT16_ELEMENTS:
28 return 1;
29 case UINT32_ELEMENTS:
30 case INT32_ELEMENTS:
31 case FLOAT32_ELEMENTS:
32 case RAB_GSAB_UINT32_ELEMENTS:
33 case RAB_GSAB_INT32_ELEMENTS:
34 case RAB_GSAB_FLOAT32_ELEMENTS:
35 return 2;
36 case PACKED_DOUBLE_ELEMENTS:
37 case HOLEY_DOUBLE_ELEMENTS:
38 case FLOAT64_ELEMENTS:
39 case BIGINT64_ELEMENTS:
40 case BIGUINT64_ELEMENTS:
41 case RAB_GSAB_FLOAT64_ELEMENTS:
42 case RAB_GSAB_BIGINT64_ELEMENTS:
43 case RAB_GSAB_BIGUINT64_ELEMENTS:
44 return 3;
45 case PACKED_SMI_ELEMENTS:
46 case PACKED_ELEMENTS:
47 case PACKED_FROZEN_ELEMENTS:
48 case PACKED_SEALED_ELEMENTS:
49 case PACKED_NONEXTENSIBLE_ELEMENTS:
50 case HOLEY_SMI_ELEMENTS:
51 case HOLEY_ELEMENTS:
52 case HOLEY_FROZEN_ELEMENTS:
53 case HOLEY_SEALED_ELEMENTS:
54 case HOLEY_NONEXTENSIBLE_ELEMENTS:
55 case DICTIONARY_ELEMENTS:
56 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
57 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
58 case FAST_STRING_WRAPPER_ELEMENTS:
59 case SLOW_STRING_WRAPPER_ELEMENTS:
60 return kTaggedSizeLog2;
61 case WASM_ARRAY_ELEMENTS:
62 case NO_ELEMENTS:
63 UNREACHABLE();
64 }
65 UNREACHABLE();
66 }
67
ElementsKindToByteSize(ElementsKind elements_kind)68 int ElementsKindToByteSize(ElementsKind elements_kind) {
69 return 1 << ElementsKindToShiftSize(elements_kind);
70 }
71
GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind)72 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
73 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
74
75 if (IsTypedArrayElementsKind(elements_kind)) {
76 return 0;
77 } else {
78 return FixedArray::kHeaderSize - kHeapObjectTag;
79 }
80 }
81
ElementsKindToString(ElementsKind kind)82 const char* ElementsKindToString(ElementsKind kind) {
83 switch (kind) {
84 case PACKED_SMI_ELEMENTS:
85 return "PACKED_SMI_ELEMENTS";
86 case HOLEY_SMI_ELEMENTS:
87 return "HOLEY_SMI_ELEMENTS";
88 case PACKED_ELEMENTS:
89 return "PACKED_ELEMENTS";
90 case HOLEY_ELEMENTS:
91 return "HOLEY_ELEMENTS";
92 case PACKED_DOUBLE_ELEMENTS:
93 return "PACKED_DOUBLE_ELEMENTS";
94 case HOLEY_DOUBLE_ELEMENTS:
95 return "HOLEY_DOUBLE_ELEMENTS";
96 case PACKED_NONEXTENSIBLE_ELEMENTS:
97 return "PACKED_NONEXTENSIBLE_ELEMENTS";
98 case HOLEY_NONEXTENSIBLE_ELEMENTS:
99 return "HOLEY_NONEXTENSIBLE_ELEMENTS";
100 case PACKED_SEALED_ELEMENTS:
101 return "PACKED_SEALED_ELEMENTS";
102 case HOLEY_SEALED_ELEMENTS:
103 return "HOLEY_SEALED_ELEMENTS";
104 case PACKED_FROZEN_ELEMENTS:
105 return "PACKED_FROZEN_ELEMENTS";
106 case HOLEY_FROZEN_ELEMENTS:
107 return "HOLEY_FROZEN_ELEMENTS";
108 case DICTIONARY_ELEMENTS:
109 return "DICTIONARY_ELEMENTS";
110 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
111 return "FAST_SLOPPY_ARGUMENTS_ELEMENTS";
112 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
113 return "SLOW_SLOPPY_ARGUMENTS_ELEMENTS";
114 case FAST_STRING_WRAPPER_ELEMENTS:
115 return "FAST_STRING_WRAPPER_ELEMENTS";
116 case SLOW_STRING_WRAPPER_ELEMENTS:
117 return "SLOW_STRING_WRAPPER_ELEMENTS";
118
119 #define PRINT_NAME(Type, type, TYPE, _) \
120 case TYPE##_ELEMENTS: \
121 return #TYPE "ELEMENTS";
122
123 TYPED_ARRAYS(PRINT_NAME);
124 RAB_GSAB_TYPED_ARRAYS(PRINT_NAME);
125 #undef PRINT_NAME
126 case WASM_ARRAY_ELEMENTS:
127 return "WASM_ARRAY_ELEMENTS";
128 case NO_ELEMENTS:
129 return "NO_ELEMENTS";
130 }
131 }
132
133 const ElementsKind kFastElementsKindSequence[kFastElementsKindCount] = {
134 PACKED_SMI_ELEMENTS, // 0
135 HOLEY_SMI_ELEMENTS, // 1
136 PACKED_DOUBLE_ELEMENTS, // 2
137 HOLEY_DOUBLE_ELEMENTS, // 3
138 PACKED_ELEMENTS, // 4
139 HOLEY_ELEMENTS // 5
140 };
141 STATIC_ASSERT(PACKED_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
142 // Verify that kFastElementsKindPackedToHoley is correct.
143 STATIC_ASSERT(PACKED_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
144 HOLEY_SMI_ELEMENTS);
145 STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
146 HOLEY_DOUBLE_ELEMENTS);
147 STATIC_ASSERT(PACKED_ELEMENTS + kFastElementsKindPackedToHoley ==
148 HOLEY_ELEMENTS);
149
GetFastElementsKindFromSequenceIndex(int sequence_number)150 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
151 DCHECK(sequence_number >= 0 && sequence_number < kFastElementsKindCount);
152 return kFastElementsKindSequence[sequence_number];
153 }
154
GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)155 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
156 for (int i = 0; i < kFastElementsKindCount; ++i) {
157 if (kFastElementsKindSequence[i] == elements_kind) {
158 return i;
159 }
160 }
161 UNREACHABLE();
162 }
163
GetNextTransitionElementsKind(ElementsKind kind)164 ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
165 int index = GetSequenceIndexFromFastElementsKind(kind);
166 return GetFastElementsKindFromSequenceIndex(index + 1);
167 }
168
IsFastTransitionTarget(ElementsKind elements_kind)169 static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
170 return IsFastElementsKind(elements_kind) ||
171 elements_kind == DICTIONARY_ELEMENTS;
172 }
173
IsMoreGeneralElementsKindTransition(ElementsKind from_kind,ElementsKind to_kind)174 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
175 ElementsKind to_kind) {
176 if (!IsFastElementsKind(from_kind)) return false;
177 if (!IsFastTransitionTarget(to_kind)) return false;
178 DCHECK(!IsTypedArrayElementsKind(from_kind));
179 DCHECK(!IsTypedArrayElementsKind(to_kind));
180 switch (from_kind) {
181 case PACKED_SMI_ELEMENTS:
182 return to_kind != PACKED_SMI_ELEMENTS;
183 case HOLEY_SMI_ELEMENTS:
184 return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS;
185 case PACKED_DOUBLE_ELEMENTS:
186 return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS &&
187 to_kind != PACKED_DOUBLE_ELEMENTS;
188 case HOLEY_DOUBLE_ELEMENTS:
189 return to_kind == PACKED_ELEMENTS || to_kind == HOLEY_ELEMENTS;
190 case PACKED_ELEMENTS:
191 return to_kind == HOLEY_ELEMENTS;
192 case HOLEY_ELEMENTS:
193 return false;
194 default:
195 return false;
196 }
197 }
198
UnionElementsKindUptoSize(ElementsKind * a_out,ElementsKind b)199 bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b) {
200 // Assert that the union of two ElementKinds can be computed via std::max.
201 static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS,
202 "ElementsKind union not computable via std::max.");
203 static_assert(HOLEY_SMI_ELEMENTS < PACKED_ELEMENTS,
204 "ElementsKind union not computable via std::max.");
205 static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS,
206 "ElementsKind union not computable via std::max.");
207 static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS,
208 "ElementsKind union not computable via std::max.");
209 ElementsKind a = *a_out;
210 switch (a) {
211 case PACKED_SMI_ELEMENTS:
212 switch (b) {
213 case PACKED_SMI_ELEMENTS:
214 case HOLEY_SMI_ELEMENTS:
215 case PACKED_ELEMENTS:
216 case HOLEY_ELEMENTS:
217 *a_out = b;
218 return true;
219 default:
220 return false;
221 }
222 case HOLEY_SMI_ELEMENTS:
223 switch (b) {
224 case PACKED_SMI_ELEMENTS:
225 case HOLEY_SMI_ELEMENTS:
226 *a_out = HOLEY_SMI_ELEMENTS;
227 return true;
228 case PACKED_ELEMENTS:
229 case HOLEY_ELEMENTS:
230 *a_out = HOLEY_ELEMENTS;
231 return true;
232 default:
233 return false;
234 }
235 case PACKED_ELEMENTS:
236 switch (b) {
237 case PACKED_SMI_ELEMENTS:
238 case PACKED_ELEMENTS:
239 *a_out = PACKED_ELEMENTS;
240 return true;
241 case HOLEY_SMI_ELEMENTS:
242 case HOLEY_ELEMENTS:
243 *a_out = HOLEY_ELEMENTS;
244 return true;
245 default:
246 return false;
247 }
248 case HOLEY_ELEMENTS:
249 switch (b) {
250 case PACKED_SMI_ELEMENTS:
251 case HOLEY_SMI_ELEMENTS:
252 case PACKED_ELEMENTS:
253 case HOLEY_ELEMENTS:
254 *a_out = HOLEY_ELEMENTS;
255 return true;
256 default:
257 return false;
258 }
259 case PACKED_DOUBLE_ELEMENTS:
260 switch (b) {
261 case PACKED_DOUBLE_ELEMENTS:
262 case HOLEY_DOUBLE_ELEMENTS:
263 *a_out = b;
264 return true;
265 default:
266 return false;
267 }
268 case HOLEY_DOUBLE_ELEMENTS:
269 switch (b) {
270 case PACKED_DOUBLE_ELEMENTS:
271 case HOLEY_DOUBLE_ELEMENTS:
272 *a_out = HOLEY_DOUBLE_ELEMENTS;
273 return true;
274 default:
275 return false;
276 }
277 default:
278 break;
279 }
280 return false;
281 }
282
283 } // namespace internal
284 } // namespace v8
285