• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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