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 #ifndef V8_ELEMENTS_KIND_H_
6 #define V8_ELEMENTS_KIND_H_
7 
8 #include "src/checks.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 enum ElementsKind {
14   // The "fast" kind for elements that only contain SMI values. Must be first
15   // to make it possible to efficiently check maps for this kind.
16   FAST_SMI_ELEMENTS,
17   FAST_HOLEY_SMI_ELEMENTS,
18 
19   // The "fast" kind for tagged values. Must be second to make it possible to
20   // efficiently check maps for this and the FAST_SMI_ONLY_ELEMENTS kind
21   // together at once.
22   FAST_ELEMENTS,
23   FAST_HOLEY_ELEMENTS,
24 
25   // The "fast" kind for unwrapped, non-tagged double values.
26   FAST_DOUBLE_ELEMENTS,
27   FAST_HOLEY_DOUBLE_ELEMENTS,
28 
29   // The "slow" kind.
30   DICTIONARY_ELEMENTS,
31   SLOPPY_ARGUMENTS_ELEMENTS,
32   // The "fast" kind for external arrays
33   EXTERNAL_INT8_ELEMENTS,
34   EXTERNAL_UINT8_ELEMENTS,
35   EXTERNAL_INT16_ELEMENTS,
36   EXTERNAL_UINT16_ELEMENTS,
37   EXTERNAL_INT32_ELEMENTS,
38   EXTERNAL_UINT32_ELEMENTS,
39   EXTERNAL_FLOAT32_ELEMENTS,
40   EXTERNAL_FLOAT64_ELEMENTS,
41   EXTERNAL_UINT8_CLAMPED_ELEMENTS,
42 
43   // Fixed typed arrays
44   UINT8_ELEMENTS,
45   INT8_ELEMENTS,
46   UINT16_ELEMENTS,
47   INT16_ELEMENTS,
48   UINT32_ELEMENTS,
49   INT32_ELEMENTS,
50   FLOAT32_ELEMENTS,
51   FLOAT64_ELEMENTS,
52   UINT8_CLAMPED_ELEMENTS,
53 
54   // Derived constants from ElementsKind
55   FIRST_ELEMENTS_KIND = FAST_SMI_ELEMENTS,
56   LAST_ELEMENTS_KIND = UINT8_CLAMPED_ELEMENTS,
57   FIRST_FAST_ELEMENTS_KIND = FAST_SMI_ELEMENTS,
58   LAST_FAST_ELEMENTS_KIND = FAST_HOLEY_DOUBLE_ELEMENTS,
59   FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_INT8_ELEMENTS,
60   LAST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_UINT8_CLAMPED_ELEMENTS,
61   FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS,
62   LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_CLAMPED_ELEMENTS,
63   TERMINAL_FAST_ELEMENTS_KIND = FAST_HOLEY_ELEMENTS
64 };
65 
66 const int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
67 const int kFastElementsKindCount = LAST_FAST_ELEMENTS_KIND -
68     FIRST_FAST_ELEMENTS_KIND + 1;
69 
70 // The number to add to a packed elements kind to reach a holey elements kind
71 const int kFastElementsKindPackedToHoley =
72     FAST_HOLEY_SMI_ELEMENTS - FAST_SMI_ELEMENTS;
73 
74 int ElementsKindToShiftSize(ElementsKind elements_kind);
75 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind);
76 const char* ElementsKindToString(ElementsKind kind);
77 
GetInitialFastElementsKind()78 inline ElementsKind GetInitialFastElementsKind() { return FAST_SMI_ELEMENTS; }
79 
80 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number);
81 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind);
82 
83 ElementsKind GetNextTransitionElementsKind(ElementsKind elements_kind);
84 
IsDictionaryElementsKind(ElementsKind kind)85 inline bool IsDictionaryElementsKind(ElementsKind kind) {
86   return kind == DICTIONARY_ELEMENTS;
87 }
88 
89 
IsSloppyArgumentsElements(ElementsKind kind)90 inline bool IsSloppyArgumentsElements(ElementsKind kind) {
91   return kind == SLOPPY_ARGUMENTS_ELEMENTS;
92 }
93 
94 
IsExternalArrayElementsKind(ElementsKind kind)95 inline bool IsExternalArrayElementsKind(ElementsKind kind) {
96   return kind >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
97       kind <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND;
98 }
99 
100 
IsTerminalElementsKind(ElementsKind kind)101 inline bool IsTerminalElementsKind(ElementsKind kind) {
102   return kind == TERMINAL_FAST_ELEMENTS_KIND ||
103       IsExternalArrayElementsKind(kind);
104 }
105 
106 
IsFixedTypedArrayElementsKind(ElementsKind kind)107 inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
108   return kind >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
109       kind <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
110 }
111 
112 
IsFastElementsKind(ElementsKind kind)113 inline bool IsFastElementsKind(ElementsKind kind) {
114   DCHECK(FIRST_FAST_ELEMENTS_KIND == 0);
115   return kind <= FAST_HOLEY_DOUBLE_ELEMENTS;
116 }
117 
118 
IsTransitionElementsKind(ElementsKind kind)119 inline bool IsTransitionElementsKind(ElementsKind kind) {
120   return IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind);
121 }
122 
123 
IsFastDoubleElementsKind(ElementsKind kind)124 inline bool IsFastDoubleElementsKind(ElementsKind kind) {
125   return kind == FAST_DOUBLE_ELEMENTS ||
126       kind == FAST_HOLEY_DOUBLE_ELEMENTS;
127 }
128 
129 
IsExternalFloatOrDoubleElementsKind(ElementsKind kind)130 inline bool IsExternalFloatOrDoubleElementsKind(ElementsKind kind) {
131   return kind == EXTERNAL_FLOAT64_ELEMENTS ||
132       kind == EXTERNAL_FLOAT32_ELEMENTS;
133 }
134 
135 
IsFixedFloatElementsKind(ElementsKind kind)136 inline bool IsFixedFloatElementsKind(ElementsKind kind) {
137   return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
138 }
139 
140 
IsDoubleOrFloatElementsKind(ElementsKind kind)141 inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
142   return IsFastDoubleElementsKind(kind) ||
143       IsExternalFloatOrDoubleElementsKind(kind) ||
144       IsFixedFloatElementsKind(kind);
145 }
146 
147 
IsFastSmiOrObjectElementsKind(ElementsKind kind)148 inline bool IsFastSmiOrObjectElementsKind(ElementsKind kind) {
149   return kind == FAST_SMI_ELEMENTS ||
150       kind == FAST_HOLEY_SMI_ELEMENTS ||
151       kind == FAST_ELEMENTS ||
152       kind == FAST_HOLEY_ELEMENTS;
153 }
154 
155 
IsFastSmiElementsKind(ElementsKind kind)156 inline bool IsFastSmiElementsKind(ElementsKind kind) {
157   return kind == FAST_SMI_ELEMENTS ||
158       kind == FAST_HOLEY_SMI_ELEMENTS;
159 }
160 
161 
IsFastObjectElementsKind(ElementsKind kind)162 inline bool IsFastObjectElementsKind(ElementsKind kind) {
163   return kind == FAST_ELEMENTS ||
164       kind == FAST_HOLEY_ELEMENTS;
165 }
166 
167 
IsFastHoleyElementsKind(ElementsKind kind)168 inline bool IsFastHoleyElementsKind(ElementsKind kind) {
169   return kind == FAST_HOLEY_SMI_ELEMENTS ||
170       kind == FAST_HOLEY_DOUBLE_ELEMENTS ||
171       kind == FAST_HOLEY_ELEMENTS;
172 }
173 
174 
IsHoleyElementsKind(ElementsKind kind)175 inline bool IsHoleyElementsKind(ElementsKind kind) {
176   return IsFastHoleyElementsKind(kind) ||
177       kind == DICTIONARY_ELEMENTS;
178 }
179 
180 
IsFastPackedElementsKind(ElementsKind kind)181 inline bool IsFastPackedElementsKind(ElementsKind kind) {
182   return kind == FAST_SMI_ELEMENTS ||
183       kind == FAST_DOUBLE_ELEMENTS ||
184       kind == FAST_ELEMENTS;
185 }
186 
187 
GetPackedElementsKind(ElementsKind holey_kind)188 inline ElementsKind GetPackedElementsKind(ElementsKind holey_kind) {
189   if (holey_kind == FAST_HOLEY_SMI_ELEMENTS) {
190     return FAST_SMI_ELEMENTS;
191   }
192   if (holey_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
193     return FAST_DOUBLE_ELEMENTS;
194   }
195   if (holey_kind == FAST_HOLEY_ELEMENTS) {
196     return FAST_ELEMENTS;
197   }
198   return holey_kind;
199 }
200 
201 
GetHoleyElementsKind(ElementsKind packed_kind)202 inline ElementsKind GetHoleyElementsKind(ElementsKind packed_kind) {
203   if (packed_kind == FAST_SMI_ELEMENTS) {
204     return FAST_HOLEY_SMI_ELEMENTS;
205   }
206   if (packed_kind == FAST_DOUBLE_ELEMENTS) {
207     return FAST_HOLEY_DOUBLE_ELEMENTS;
208   }
209   if (packed_kind == FAST_ELEMENTS) {
210     return FAST_HOLEY_ELEMENTS;
211   }
212   return packed_kind;
213 }
214 
215 
FastSmiToObjectElementsKind(ElementsKind from_kind)216 inline ElementsKind FastSmiToObjectElementsKind(ElementsKind from_kind) {
217   DCHECK(IsFastSmiElementsKind(from_kind));
218   return (from_kind == FAST_SMI_ELEMENTS)
219       ? FAST_ELEMENTS
220       : FAST_HOLEY_ELEMENTS;
221 }
222 
223 
IsSimpleMapChangeTransition(ElementsKind from_kind,ElementsKind to_kind)224 inline bool IsSimpleMapChangeTransition(ElementsKind from_kind,
225                                         ElementsKind to_kind) {
226   return (GetHoleyElementsKind(from_kind) == to_kind) ||
227       (IsFastSmiElementsKind(from_kind) &&
228        IsFastObjectElementsKind(to_kind));
229 }
230 
231 
232 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
233                                          ElementsKind to_kind);
234 
235 
IsTransitionableFastElementsKind(ElementsKind from_kind)236 inline bool IsTransitionableFastElementsKind(ElementsKind from_kind) {
237   return IsFastElementsKind(from_kind) &&
238       from_kind != TERMINAL_FAST_ELEMENTS_KIND;
239 }
240 
241 
242 ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind,
243                                                 bool allow_only_packed);
244 
245 
CanTransitionToMoreGeneralFastElementsKind(ElementsKind elements_kind,bool allow_only_packed)246 inline bool CanTransitionToMoreGeneralFastElementsKind(
247     ElementsKind elements_kind,
248     bool allow_only_packed) {
249   return IsFastElementsKind(elements_kind) &&
250       (elements_kind != TERMINAL_FAST_ELEMENTS_KIND &&
251        (!allow_only_packed || elements_kind != FAST_ELEMENTS));
252 }
253 
254 
255 } }  // namespace v8::internal
256 
257 #endif  // V8_ELEMENTS_KIND_H_
258