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