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