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 UINT8_ELEMENTS:
19    case INT8_ELEMENTS:
20    case UINT8_CLAMPED_ELEMENTS:
21      return 0;
22    case UINT16_ELEMENTS:
23    case INT16_ELEMENTS:
24      return 1;
25    case UINT32_ELEMENTS:
26    case INT32_ELEMENTS:
27    case FLOAT32_ELEMENTS:
28      return 2;
29    case FAST_DOUBLE_ELEMENTS:
30    case FAST_HOLEY_DOUBLE_ELEMENTS:
31    case FLOAT64_ELEMENTS:
32      return 3;
33    case FAST_SMI_ELEMENTS:
34    case FAST_ELEMENTS:
35    case FAST_HOLEY_SMI_ELEMENTS:
36    case FAST_HOLEY_ELEMENTS:
37    case DICTIONARY_ELEMENTS:
38    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
39    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
40      return kPointerSizeLog2;
41  }
42  UNREACHABLE();
43  return 0;
44}
45
46
47int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
48  STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
49
50  if (IsFixedTypedArrayElementsKind(elements_kind)) {
51    return 0;
52  } else {
53    return FixedArray::kHeaderSize - kHeapObjectTag;
54  }
55}
56
57
58const char* ElementsKindToString(ElementsKind kind) {
59  ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
60  return accessor->name();
61}
62
63
64struct InitializeFastElementsKindSequence {
65  static void Construct(
66      ElementsKind** fast_elements_kind_sequence_ptr) {
67    ElementsKind* fast_elements_kind_sequence =
68        new ElementsKind[kFastElementsKindCount];
69    *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
70    STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
71    fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS;
72    fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS;
73    fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS;
74    fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS;
75    fast_elements_kind_sequence[4] = FAST_ELEMENTS;
76    fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS;
77
78    // Verify that kFastElementsKindPackedToHoley is correct.
79    STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
80                  FAST_HOLEY_SMI_ELEMENTS);
81    STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
82                  FAST_HOLEY_DOUBLE_ELEMENTS);
83    STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley ==
84                  FAST_HOLEY_ELEMENTS);
85  }
86};
87
88
89static base::LazyInstance<ElementsKind*,
90                          InitializeFastElementsKindSequence>::type
91    fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;
92
93
94ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
95  DCHECK(sequence_number >= 0 &&
96         sequence_number < kFastElementsKindCount);
97  return fast_elements_kind_sequence.Get()[sequence_number];
98}
99
100
101int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
102  for (int i = 0; i < kFastElementsKindCount; ++i) {
103    if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
104      return i;
105    }
106  }
107  UNREACHABLE();
108  return 0;
109}
110
111
112ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
113  int index = GetSequenceIndexFromFastElementsKind(kind);
114  return GetFastElementsKindFromSequenceIndex(index + 1);
115}
116
117
118static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
119  return IsFastElementsKind(elements_kind) ||
120      elements_kind == DICTIONARY_ELEMENTS;
121}
122
123bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
124                                         ElementsKind to_kind) {
125  if (IsFixedTypedArrayElementsKind(from_kind) ||
126      IsFixedTypedArrayElementsKind(to_kind)) {
127    return false;
128  }
129  if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) {
130    switch (from_kind) {
131      case FAST_SMI_ELEMENTS:
132        return to_kind != FAST_SMI_ELEMENTS;
133      case FAST_HOLEY_SMI_ELEMENTS:
134        return to_kind != FAST_SMI_ELEMENTS &&
135            to_kind != FAST_HOLEY_SMI_ELEMENTS;
136      case FAST_DOUBLE_ELEMENTS:
137        return to_kind != FAST_SMI_ELEMENTS &&
138            to_kind != FAST_HOLEY_SMI_ELEMENTS &&
139            to_kind != FAST_DOUBLE_ELEMENTS;
140      case FAST_HOLEY_DOUBLE_ELEMENTS:
141        return to_kind == FAST_ELEMENTS ||
142            to_kind == FAST_HOLEY_ELEMENTS;
143      case FAST_ELEMENTS:
144        return to_kind == FAST_HOLEY_ELEMENTS;
145      case FAST_HOLEY_ELEMENTS:
146        return false;
147      default:
148        return false;
149    }
150  }
151  return false;
152}
153
154
155}  // namespace internal
156}  // namespace v8
157