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/api.h"
8 #include "src/base/lazy-instance.h"
9 #include "src/elements.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 EXTERNAL_INT8_ELEMENTS:
19 case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
20 case EXTERNAL_UINT8_ELEMENTS:
21 case UINT8_ELEMENTS:
22 case INT8_ELEMENTS:
23 case UINT8_CLAMPED_ELEMENTS:
24 return 0;
25 case EXTERNAL_INT16_ELEMENTS:
26 case EXTERNAL_UINT16_ELEMENTS:
27 case UINT16_ELEMENTS:
28 case INT16_ELEMENTS:
29 return 1;
30 case EXTERNAL_INT32_ELEMENTS:
31 case EXTERNAL_UINT32_ELEMENTS:
32 case EXTERNAL_FLOAT32_ELEMENTS:
33 case UINT32_ELEMENTS:
34 case INT32_ELEMENTS:
35 case FLOAT32_ELEMENTS:
36 return 2;
37 case EXTERNAL_FLOAT64_ELEMENTS:
38 case FAST_DOUBLE_ELEMENTS:
39 case FAST_HOLEY_DOUBLE_ELEMENTS:
40 case FLOAT64_ELEMENTS:
41 return 3;
42 case FAST_SMI_ELEMENTS:
43 case FAST_ELEMENTS:
44 case FAST_HOLEY_SMI_ELEMENTS:
45 case FAST_HOLEY_ELEMENTS:
46 case DICTIONARY_ELEMENTS:
47 case SLOPPY_ARGUMENTS_ELEMENTS:
48 return kPointerSizeLog2;
49 }
50 UNREACHABLE();
51 return 0;
52 }
53
54
GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind)55 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
56 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
57 return IsExternalArrayElementsKind(elements_kind)
58 ? 0 : (FixedArray::kHeaderSize - kHeapObjectTag);
59 }
60
61
ElementsKindToString(ElementsKind kind)62 const char* ElementsKindToString(ElementsKind kind) {
63 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
64 return accessor->name();
65 }
66
67
PrintElementsKind(FILE * out,ElementsKind kind)68 void PrintElementsKind(FILE* out, ElementsKind kind) {
69 PrintF(out, "%s", ElementsKindToString(kind));
70 }
71
72
GetInitialFastElementsKind()73 ElementsKind GetInitialFastElementsKind() {
74 if (FLAG_packed_arrays) {
75 return FAST_SMI_ELEMENTS;
76 } else {
77 return FAST_HOLEY_SMI_ELEMENTS;
78 }
79 }
80
81
82 struct InitializeFastElementsKindSequence {
Constructv8::internal::InitializeFastElementsKindSequence83 static void Construct(
84 ElementsKind** fast_elements_kind_sequence_ptr) {
85 ElementsKind* fast_elements_kind_sequence =
86 new ElementsKind[kFastElementsKindCount];
87 *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
88 STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
89 fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS;
90 fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS;
91 fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS;
92 fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS;
93 fast_elements_kind_sequence[4] = FAST_ELEMENTS;
94 fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS;
95
96 // Verify that kFastElementsKindPackedToHoley is correct.
97 STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
98 FAST_HOLEY_SMI_ELEMENTS);
99 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
100 FAST_HOLEY_DOUBLE_ELEMENTS);
101 STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley ==
102 FAST_HOLEY_ELEMENTS);
103 }
104 };
105
106
107 static base::LazyInstance<ElementsKind*,
108 InitializeFastElementsKindSequence>::type
109 fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;
110
111
GetFastElementsKindFromSequenceIndex(int sequence_number)112 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
113 ASSERT(sequence_number >= 0 &&
114 sequence_number < kFastElementsKindCount);
115 return fast_elements_kind_sequence.Get()[sequence_number];
116 }
117
118
GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)119 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
120 for (int i = 0; i < kFastElementsKindCount; ++i) {
121 if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
122 return i;
123 }
124 }
125 UNREACHABLE();
126 return 0;
127 }
128
129
GetNextTransitionElementsKind(ElementsKind kind)130 ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
131 switch (kind) {
132 #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
133 case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
134
135 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE)
136 #undef FIXED_TYPED_ARRAY_CASE
137 default: {
138 int index = GetSequenceIndexFromFastElementsKind(kind);
139 return GetFastElementsKindFromSequenceIndex(index + 1);
140 }
141 }
142 }
143
144
GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind,bool allow_only_packed)145 ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind,
146 bool allow_only_packed) {
147 ASSERT(IsFastElementsKind(elements_kind));
148 ASSERT(elements_kind != TERMINAL_FAST_ELEMENTS_KIND);
149 while (true) {
150 elements_kind = GetNextTransitionElementsKind(elements_kind);
151 if (!IsFastHoleyElementsKind(elements_kind) || !allow_only_packed) {
152 return elements_kind;
153 }
154 }
155 UNREACHABLE();
156 return TERMINAL_FAST_ELEMENTS_KIND;
157 }
158
159
IsTypedArrayElementsKind(ElementsKind elements_kind)160 static bool IsTypedArrayElementsKind(ElementsKind elements_kind) {
161 return IsFixedTypedArrayElementsKind(elements_kind) ||
162 IsExternalArrayElementsKind(elements_kind);
163 }
164
165
IsFastTransitionTarget(ElementsKind elements_kind)166 static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
167 return IsFastElementsKind(elements_kind) ||
168 elements_kind == DICTIONARY_ELEMENTS;
169 }
170
IsMoreGeneralElementsKindTransition(ElementsKind from_kind,ElementsKind to_kind)171 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
172 ElementsKind to_kind) {
173 if (IsTypedArrayElementsKind(from_kind) ||
174 IsTypedArrayElementsKind(to_kind)) {
175 switch (from_kind) {
176 #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
177 case TYPE##_ELEMENTS: \
178 return to_kind == EXTERNAL_##TYPE##_ELEMENTS;
179
180 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE);
181 #undef FIXED_TYPED_ARRAY_CASE
182 default:
183 return false;
184 }
185 }
186 if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) {
187 switch (from_kind) {
188 case FAST_SMI_ELEMENTS:
189 return to_kind != FAST_SMI_ELEMENTS;
190 case FAST_HOLEY_SMI_ELEMENTS:
191 return to_kind != FAST_SMI_ELEMENTS &&
192 to_kind != FAST_HOLEY_SMI_ELEMENTS;
193 case FAST_DOUBLE_ELEMENTS:
194 return to_kind != FAST_SMI_ELEMENTS &&
195 to_kind != FAST_HOLEY_SMI_ELEMENTS &&
196 to_kind != FAST_DOUBLE_ELEMENTS;
197 case FAST_HOLEY_DOUBLE_ELEMENTS:
198 return to_kind == FAST_ELEMENTS ||
199 to_kind == FAST_HOLEY_ELEMENTS;
200 case FAST_ELEMENTS:
201 return to_kind == FAST_HOLEY_ELEMENTS;
202 case FAST_HOLEY_ELEMENTS:
203 return false;
204 default:
205 return false;
206 }
207 }
208 return false;
209 }
210
211
212 } } // namespace v8::internal
213