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.
5 #include "src/elements-kind.h"
8 #include "src/base/lazy-instance.h"
9 #include "src/elements.h"
10 #include "src/objects.h"
16 int ElementsKindToShiftSize(ElementsKind elements_kind) {
17 switch (elements_kind) {
18 case EXTERNAL_INT8_ELEMENTS:
19 case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
20 case EXTERNAL_UINT8_ELEMENTS:
23 case UINT8_CLAMPED_ELEMENTS:
25 case EXTERNAL_INT16_ELEMENTS:
26 case EXTERNAL_UINT16_ELEMENTS:
30 case EXTERNAL_INT32_ELEMENTS:
31 case EXTERNAL_UINT32_ELEMENTS:
32 case EXTERNAL_FLOAT32_ELEMENTS:
35 case FLOAT32_ELEMENTS:
37 case EXTERNAL_FLOAT64_ELEMENTS:
38 case FAST_DOUBLE_ELEMENTS:
39 case FAST_HOLEY_DOUBLE_ELEMENTS:
40 case FLOAT64_ELEMENTS:
42 case EXTERNAL_FLOAT32x4_ELEMENTS:
43 case EXTERNAL_FLOAT64x2_ELEMENTS:
44 case EXTERNAL_INT32x4_ELEMENTS:
45 case FLOAT32x4_ELEMENTS:
46 case FLOAT64x2_ELEMENTS:
47 case INT32x4_ELEMENTS:
49 case FAST_SMI_ELEMENTS:
51 case FAST_HOLEY_SMI_ELEMENTS:
52 case FAST_HOLEY_ELEMENTS:
53 case DICTIONARY_ELEMENTS:
54 case SLOPPY_ARGUMENTS_ELEMENTS:
55 return kPointerSizeLog2;
62 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
63 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
64 return IsExternalArrayElementsKind(elements_kind)
65 ? 0 : (FixedArray::kHeaderSize - kHeapObjectTag);
69 const char* ElementsKindToString(ElementsKind kind) {
70 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
71 return accessor->name();
75 void PrintElementsKind(FILE* out, ElementsKind kind) {
76 PrintF(out, "%s", ElementsKindToString(kind));
80 ElementsKind GetInitialFastElementsKind() {
81 if (FLAG_packed_arrays) {
82 return FAST_SMI_ELEMENTS;
84 return FAST_HOLEY_SMI_ELEMENTS;
89 struct InitializeFastElementsKindSequence {
90 static void Construct(
91 ElementsKind** fast_elements_kind_sequence_ptr) {
92 ElementsKind* fast_elements_kind_sequence =
93 new ElementsKind[kFastElementsKindCount];
94 *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
95 STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
96 fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS;
97 fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS;
98 fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS;
99 fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS;
100 fast_elements_kind_sequence[4] = FAST_ELEMENTS;
101 fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS;
103 // Verify that kFastElementsKindPackedToHoley is correct.
104 STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
105 FAST_HOLEY_SMI_ELEMENTS);
106 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
107 FAST_HOLEY_DOUBLE_ELEMENTS);
108 STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley ==
109 FAST_HOLEY_ELEMENTS);
114 static base::LazyInstance<ElementsKind*,
115 InitializeFastElementsKindSequence>::type
116 fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;
119 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
120 ASSERT(sequence_number >= 0 &&
121 sequence_number < kFastElementsKindCount);
122 return fast_elements_kind_sequence.Get()[sequence_number];
126 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
127 for (int i = 0; i < kFastElementsKindCount; ++i) {
128 if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
137 ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
139 #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
140 case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
142 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE)
143 #undef FIXED_TYPED_ARRAY_CASE
145 int index = GetSequenceIndexFromFastElementsKind(kind);
146 return GetFastElementsKindFromSequenceIndex(index + 1);
152 ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind,
153 bool allow_only_packed) {
154 ASSERT(IsFastElementsKind(elements_kind));
155 ASSERT(elements_kind != TERMINAL_FAST_ELEMENTS_KIND);
157 elements_kind = GetNextTransitionElementsKind(elements_kind);
158 if (!IsFastHoleyElementsKind(elements_kind) || !allow_only_packed) {
159 return elements_kind;
163 return TERMINAL_FAST_ELEMENTS_KIND;
167 static bool IsTypedArrayElementsKind(ElementsKind elements_kind) {
168 return IsFixedTypedArrayElementsKind(elements_kind) ||
169 IsExternalArrayElementsKind(elements_kind);
173 static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
174 return IsFastElementsKind(elements_kind) ||
175 elements_kind == DICTIONARY_ELEMENTS;
178 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
179 ElementsKind to_kind) {
180 if (IsTypedArrayElementsKind(from_kind) ||
181 IsTypedArrayElementsKind(to_kind)) {
183 #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
184 case TYPE##_ELEMENTS: \
185 return to_kind == EXTERNAL_##TYPE##_ELEMENTS;
187 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE);
188 #undef FIXED_TYPED_ARRAY_CASE
193 if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) {
195 case FAST_SMI_ELEMENTS:
196 return to_kind != FAST_SMI_ELEMENTS;
197 case FAST_HOLEY_SMI_ELEMENTS:
198 return to_kind != FAST_SMI_ELEMENTS &&
199 to_kind != FAST_HOLEY_SMI_ELEMENTS;
200 case FAST_DOUBLE_ELEMENTS:
201 return to_kind != FAST_SMI_ELEMENTS &&
202 to_kind != FAST_HOLEY_SMI_ELEMENTS &&
203 to_kind != FAST_DOUBLE_ELEMENTS;
204 case FAST_HOLEY_DOUBLE_ELEMENTS:
205 return to_kind == FAST_ELEMENTS ||
206 to_kind == FAST_HOLEY_ELEMENTS;
208 return to_kind == FAST_HOLEY_ELEMENTS;
209 case FAST_HOLEY_ELEMENTS:
219 } } // namespace v8::internal