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 | |
12 | namespace v8 { |
13 | namespace internal { |
14 | |
15 | |
16 | int 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 | |
53 | int ElementsKindToByteSize(ElementsKind elements_kind) { |
54 | return 1 << ElementsKindToShiftSize(elements_kind); |
55 | } |
56 | |
57 | int (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 | |
68 | const char* ElementsKindToString(ElementsKind kind) { |
69 | ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); |
70 | return accessor->name(); |
71 | } |
72 | |
73 | ElementsKind 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 | }; |
81 | STATIC_ASSERT(PACKED_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND); |
82 | // Verify that kFastElementsKindPackedToHoley is correct. |
83 | STATIC_ASSERT(PACKED_SMI_ELEMENTS + kFastElementsKindPackedToHoley == |
84 | HOLEY_SMI_ELEMENTS); |
85 | STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley == |
86 | HOLEY_DOUBLE_ELEMENTS); |
87 | STATIC_ASSERT(PACKED_ELEMENTS + kFastElementsKindPackedToHoley == |
88 | HOLEY_ELEMENTS); |
89 | |
90 | ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) { |
91 | DCHECK(sequence_number >= 0 && |
92 | sequence_number < kFastElementsKindCount); |
93 | return kFastElementsKindSequence[sequence_number]; |
94 | } |
95 | |
96 | int 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 | |
106 | ElementsKind GetNextTransitionElementsKind(ElementsKind kind) { |
107 | int index = GetSequenceIndexFromFastElementsKind(kind); |
108 | return GetFastElementsKindFromSequenceIndex(index + 1); |
109 | } |
110 | |
111 | |
112 | static inline bool IsFastTransitionTarget(ElementsKind elements_kind) { |
113 | return IsFastElementsKind(elements_kind) || |
114 | elements_kind == DICTIONARY_ELEMENTS; |
115 | } |
116 | |
117 | bool 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 | |
142 | bool 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 | |