blob: 0ebc6dc246b09e7dcb9296bfc138a5457210870f [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
12namespace v8 {
13namespace internal {
14
15
16int 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
55int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
56 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
57 return IsExternalArrayElementsKind(elements_kind)
58 ? 0 : (FixedArray::kHeaderSize - kHeapObjectTag);
59}
60
61
62const char* ElementsKindToString(ElementsKind kind) {
63 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
64 return accessor->name();
65}
66
67
68struct InitializeFastElementsKindSequence {
69 static void Construct(
70 ElementsKind** fast_elements_kind_sequence_ptr) {
71 ElementsKind* fast_elements_kind_sequence =
72 new ElementsKind[kFastElementsKindCount];
73 *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
74 STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
75 fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS;
76 fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS;
77 fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS;
78 fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS;
79 fast_elements_kind_sequence[4] = FAST_ELEMENTS;
80 fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS;
81
82 // Verify that kFastElementsKindPackedToHoley is correct.
83 STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
84 FAST_HOLEY_SMI_ELEMENTS);
85 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
86 FAST_HOLEY_DOUBLE_ELEMENTS);
87 STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley ==
88 FAST_HOLEY_ELEMENTS);
89 }
90};
91
92
93static base::LazyInstance<ElementsKind*,
94 InitializeFastElementsKindSequence>::type
95 fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;
96
97
98ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
99 DCHECK(sequence_number >= 0 &&
100 sequence_number < kFastElementsKindCount);
101 return fast_elements_kind_sequence.Get()[sequence_number];
102}
103
104
105int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
106 for (int i = 0; i < kFastElementsKindCount; ++i) {
107 if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
108 return i;
109 }
110 }
111 UNREACHABLE();
112 return 0;
113}
114
115
116ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
117 switch (kind) {
118#define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
119 case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
120
121 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE)
122#undef FIXED_TYPED_ARRAY_CASE
123 default: {
124 int index = GetSequenceIndexFromFastElementsKind(kind);
125 return GetFastElementsKindFromSequenceIndex(index + 1);
126 }
127 }
128}
129
130
131ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind,
132 bool allow_only_packed) {
133 DCHECK(IsFastElementsKind(elements_kind));
134 DCHECK(elements_kind != TERMINAL_FAST_ELEMENTS_KIND);
135 while (true) {
136 elements_kind = GetNextTransitionElementsKind(elements_kind);
137 if (!IsFastHoleyElementsKind(elements_kind) || !allow_only_packed) {
138 return elements_kind;
139 }
140 }
141 UNREACHABLE();
142 return TERMINAL_FAST_ELEMENTS_KIND;
143}
144
145
146static bool IsTypedArrayElementsKind(ElementsKind elements_kind) {
147 return IsFixedTypedArrayElementsKind(elements_kind) ||
148 IsExternalArrayElementsKind(elements_kind);
149}
150
151
152static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
153 return IsFastElementsKind(elements_kind) ||
154 elements_kind == DICTIONARY_ELEMENTS;
155}
156
157bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
158 ElementsKind to_kind) {
159 if (IsTypedArrayElementsKind(from_kind) ||
160 IsTypedArrayElementsKind(to_kind)) {
161 switch (from_kind) {
162#define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
163 case TYPE##_ELEMENTS: \
164 return to_kind == EXTERNAL_##TYPE##_ELEMENTS;
165
166 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE);
167#undef FIXED_TYPED_ARRAY_CASE
168 default:
169 return false;
170 }
171 }
172 if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) {
173 switch (from_kind) {
174 case FAST_SMI_ELEMENTS:
175 return to_kind != FAST_SMI_ELEMENTS;
176 case FAST_HOLEY_SMI_ELEMENTS:
177 return to_kind != FAST_SMI_ELEMENTS &&
178 to_kind != FAST_HOLEY_SMI_ELEMENTS;
179 case FAST_DOUBLE_ELEMENTS:
180 return to_kind != FAST_SMI_ELEMENTS &&
181 to_kind != FAST_HOLEY_SMI_ELEMENTS &&
182 to_kind != FAST_DOUBLE_ELEMENTS;
183 case FAST_HOLEY_DOUBLE_ELEMENTS:
184 return to_kind == FAST_ELEMENTS ||
185 to_kind == FAST_HOLEY_ELEMENTS;
186 case FAST_ELEMENTS:
187 return to_kind == FAST_HOLEY_ELEMENTS;
188 case FAST_HOLEY_ELEMENTS:
189 return false;
190 default:
191 return false;
192 }
193 }
194 return false;
195}
196
197
198} } // namespace v8::internal