• 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/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 
ElementsKindToShiftSize(ElementsKind elements_kind)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 HOLEY_SMI_ELEMENTS:
38     case HOLEY_ELEMENTS:
39     case DICTIONARY_ELEMENTS:
40     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
41     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
42     case FAST_STRING_WRAPPER_ELEMENTS:
43     case SLOW_STRING_WRAPPER_ELEMENTS:
44       return kPointerSizeLog2;
45     case NO_ELEMENTS:
46       UNREACHABLE();
47   }
48   UNREACHABLE();
49 }
50 
ElementsKindToByteSize(ElementsKind elements_kind)51 int ElementsKindToByteSize(ElementsKind elements_kind) {
52   return 1 << ElementsKindToShiftSize(elements_kind);
53 }
54 
GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind)55 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
56   STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
57 
58   if (IsFixedTypedArrayElementsKind(elements_kind)) {
59     return 0;
60   } else {
61     return FixedArray::kHeaderSize - kHeapObjectTag;
62   }
63 }
64 
65 
ElementsKindToString(ElementsKind kind)66 const char* ElementsKindToString(ElementsKind kind) {
67   ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
68   return accessor->name();
69 }
70 
71 
72 struct InitializeFastElementsKindSequence {
Constructv8::internal::InitializeFastElementsKindSequence73   static void Construct(void* fast_elements_kind_sequence_ptr_arg) {
74     auto fast_elements_kind_sequence_ptr =
75         reinterpret_cast<ElementsKind**>(fast_elements_kind_sequence_ptr_arg);
76     ElementsKind* fast_elements_kind_sequence =
77         new ElementsKind[kFastElementsKindCount];
78     *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
79     STATIC_ASSERT(PACKED_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
80     fast_elements_kind_sequence[0] = PACKED_SMI_ELEMENTS;
81     fast_elements_kind_sequence[1] = HOLEY_SMI_ELEMENTS;
82     fast_elements_kind_sequence[2] = PACKED_DOUBLE_ELEMENTS;
83     fast_elements_kind_sequence[3] = HOLEY_DOUBLE_ELEMENTS;
84     fast_elements_kind_sequence[4] = PACKED_ELEMENTS;
85     fast_elements_kind_sequence[5] = HOLEY_ELEMENTS;
86 
87     // Verify that kFastElementsKindPackedToHoley is correct.
88     STATIC_ASSERT(PACKED_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
89                   HOLEY_SMI_ELEMENTS);
90     STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
91                   HOLEY_DOUBLE_ELEMENTS);
92     STATIC_ASSERT(PACKED_ELEMENTS + kFastElementsKindPackedToHoley ==
93                   HOLEY_ELEMENTS);
94   }
95 };
96 
97 
98 static base::LazyInstance<ElementsKind*,
99                           InitializeFastElementsKindSequence>::type
100     fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;
101 
102 
GetFastElementsKindFromSequenceIndex(int sequence_number)103 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
104   DCHECK(sequence_number >= 0 &&
105          sequence_number < kFastElementsKindCount);
106   return fast_elements_kind_sequence.Get()[sequence_number];
107 }
108 
109 
GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)110 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
111   for (int i = 0; i < kFastElementsKindCount; ++i) {
112     if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
113       return i;
114     }
115   }
116   UNREACHABLE();
117 }
118 
119 
GetNextTransitionElementsKind(ElementsKind kind)120 ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
121   int index = GetSequenceIndexFromFastElementsKind(kind);
122   return GetFastElementsKindFromSequenceIndex(index + 1);
123 }
124 
125 
IsFastTransitionTarget(ElementsKind elements_kind)126 static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
127   return IsFastElementsKind(elements_kind) ||
128       elements_kind == DICTIONARY_ELEMENTS;
129 }
130 
IsMoreGeneralElementsKindTransition(ElementsKind from_kind,ElementsKind to_kind)131 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
132                                          ElementsKind to_kind) {
133   if (!IsFastElementsKind(from_kind)) return false;
134   if (!IsFastTransitionTarget(to_kind)) return false;
135   DCHECK(!IsFixedTypedArrayElementsKind(from_kind));
136   DCHECK(!IsFixedTypedArrayElementsKind(to_kind));
137   switch (from_kind) {
138     case PACKED_SMI_ELEMENTS:
139       return to_kind != PACKED_SMI_ELEMENTS;
140     case HOLEY_SMI_ELEMENTS:
141       return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS;
142     case PACKED_DOUBLE_ELEMENTS:
143       return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS &&
144              to_kind != PACKED_DOUBLE_ELEMENTS;
145     case HOLEY_DOUBLE_ELEMENTS:
146       return to_kind == PACKED_ELEMENTS || to_kind == HOLEY_ELEMENTS;
147     case PACKED_ELEMENTS:
148       return to_kind == HOLEY_ELEMENTS;
149     case HOLEY_ELEMENTS:
150       return false;
151     default:
152       return false;
153   }
154 }
155 
UnionElementsKindUptoSize(ElementsKind * a_out,ElementsKind b)156 bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b) {
157   // Assert that the union of two ElementKinds can be computed via std::max.
158   static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS,
159                 "ElementsKind union not computable via std::max.");
160   static_assert(HOLEY_SMI_ELEMENTS < PACKED_ELEMENTS,
161                 "ElementsKind union not computable via std::max.");
162   static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS,
163                 "ElementsKind union not computable via std::max.");
164   static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS,
165                 "ElementsKind union not computable via std::max.");
166   ElementsKind a = *a_out;
167   switch (a) {
168     case PACKED_SMI_ELEMENTS:
169       switch (b) {
170         case PACKED_SMI_ELEMENTS:
171         case HOLEY_SMI_ELEMENTS:
172         case PACKED_ELEMENTS:
173         case HOLEY_ELEMENTS:
174           *a_out = b;
175           return true;
176         default:
177           return false;
178       }
179     case HOLEY_SMI_ELEMENTS:
180       switch (b) {
181         case PACKED_SMI_ELEMENTS:
182         case HOLEY_SMI_ELEMENTS:
183           *a_out = HOLEY_SMI_ELEMENTS;
184           return true;
185         case PACKED_ELEMENTS:
186         case HOLEY_ELEMENTS:
187           *a_out = HOLEY_ELEMENTS;
188           return true;
189         default:
190           return false;
191       }
192     case PACKED_ELEMENTS:
193       switch (b) {
194         case PACKED_SMI_ELEMENTS:
195         case PACKED_ELEMENTS:
196           *a_out = PACKED_ELEMENTS;
197           return true;
198         case HOLEY_SMI_ELEMENTS:
199         case HOLEY_ELEMENTS:
200           *a_out = HOLEY_ELEMENTS;
201           return true;
202         default:
203           return false;
204       }
205     case HOLEY_ELEMENTS:
206       switch (b) {
207         case PACKED_SMI_ELEMENTS:
208         case HOLEY_SMI_ELEMENTS:
209         case PACKED_ELEMENTS:
210         case HOLEY_ELEMENTS:
211           *a_out = HOLEY_ELEMENTS;
212           return true;
213         default:
214           return false;
215       }
216       break;
217     case PACKED_DOUBLE_ELEMENTS:
218       switch (b) {
219         case PACKED_DOUBLE_ELEMENTS:
220         case HOLEY_DOUBLE_ELEMENTS:
221           *a_out = b;
222           return true;
223         default:
224           return false;
225       }
226     case HOLEY_DOUBLE_ELEMENTS:
227       switch (b) {
228         case PACKED_DOUBLE_ELEMENTS:
229         case HOLEY_DOUBLE_ELEMENTS:
230           *a_out = HOLEY_DOUBLE_ELEMENTS;
231           return true;
232         default:
233           return false;
234       }
235 
236       break;
237     default:
238       break;
239   }
240   return false;
241 }
242 
243 }  // namespace internal
244 }  // namespace v8
245