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
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
199