• 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/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