• 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       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