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