elements-kind.h 8.2 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_ELEMENTS_KIND_H_
#define V8_ELEMENTS_KIND_H_

8
#include "src/base/macros.h"
9
#include "src/checks.h"
10 11 12 13 14 15 16

namespace v8 {
namespace internal {

enum ElementsKind {
  // The "fast" kind for elements that only contain SMI values. Must be first
  // to make it possible to efficiently check maps for this kind.
17 18
  PACKED_SMI_ELEMENTS,
  HOLEY_SMI_ELEMENTS,
19 20

  // The "fast" kind for tagged values. Must be second to make it possible to
21
  // efficiently check maps for this and the PACKED_SMI_ELEMENTS kind
22
  // together at once.
23 24
  PACKED_ELEMENTS,
  HOLEY_ELEMENTS,
25 26

  // The "fast" kind for unwrapped, non-tagged double values.
27 28
  PACKED_DOUBLE_ELEMENTS,
  HOLEY_DOUBLE_ELEMENTS,
29 30 31

  // The "slow" kind.
  DICTIONARY_ELEMENTS,
32

33
  // Elements kind of the "arguments" object (only in sloppy mode).
34 35 36
  FAST_SLOPPY_ARGUMENTS_ELEMENTS,
  SLOW_SLOPPY_ARGUMENTS_ELEMENTS,

37 38 39 40 41 42
  // For string wrapper objects ("new String('...')"), the string's characters
  // are overlaid onto a regular elements backing store.
  FAST_STRING_WRAPPER_ELEMENTS,
  SLOW_STRING_WRAPPER_ELEMENTS,

  // Fixed typed arrays.
43 44 45 46 47 48 49 50 51
  UINT8_ELEMENTS,
  INT8_ELEMENTS,
  UINT16_ELEMENTS,
  INT16_ELEMENTS,
  UINT32_ELEMENTS,
  INT32_ELEMENTS,
  FLOAT32_ELEMENTS,
  FLOAT64_ELEMENTS,
  UINT8_CLAMPED_ELEMENTS,
52 53
  BIGUINT64_ELEMENTS,
  BIGINT64_ELEMENTS,
54

55 56 57 58
  // Sentinel ElementsKind for objects with no elements.
  NO_ELEMENTS,

  // Derived constants from ElementsKind.
59
  FIRST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS,
60
  LAST_ELEMENTS_KIND = BIGINT64_ELEMENTS,
61 62
  FIRST_FAST_ELEMENTS_KIND = PACKED_SMI_ELEMENTS,
  LAST_FAST_ELEMENTS_KIND = HOLEY_DOUBLE_ELEMENTS,
63
  FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS,
64
  LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = BIGINT64_ELEMENTS,
65
  TERMINAL_FAST_ELEMENTS_KIND = HOLEY_ELEMENTS
66 67 68
};

const int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
69 70
const int kFastElementsKindCount =
    LAST_FAST_ELEMENTS_KIND - FIRST_FAST_ELEMENTS_KIND + 1;
71

72 73
// The number to add to a packed elements kind to reach a holey elements kind
const int kFastElementsKindPackedToHoley =
74
    HOLEY_SMI_ELEMENTS - PACKED_SMI_ELEMENTS;
75

76
int ElementsKindToShiftSize(ElementsKind elements_kind);
77
int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind);
78
const char* ElementsKindToString(ElementsKind kind);
79

80
inline ElementsKind GetInitialFastElementsKind() { return PACKED_SMI_ELEMENTS; }
81

82
ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number);
83 84
int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind);

85
ElementsKind GetNextTransitionElementsKind(ElementsKind elements_kind);
86

87 88 89 90
inline bool IsDictionaryElementsKind(ElementsKind kind) {
  return kind == DICTIONARY_ELEMENTS;
}

91
inline bool IsSloppyArgumentsElementsKind(ElementsKind kind) {
92 93
  return kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
         kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
94 95
}

96 97 98 99
inline bool IsStringWrapperElementsKind(ElementsKind kind) {
  return kind == FAST_STRING_WRAPPER_ELEMENTS ||
         kind == SLOW_STRING_WRAPPER_ELEMENTS;
}
100

101 102 103
inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
  return kind >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
         kind <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
104 105
}

106 107
inline bool IsTerminalElementsKind(ElementsKind kind) {
  return kind == TERMINAL_FAST_ELEMENTS_KIND ||
108
         IsFixedTypedArrayElementsKind(kind);
109 110
}

111
inline bool IsFastElementsKind(ElementsKind kind) {
112
  STATIC_ASSERT(FIRST_FAST_ELEMENTS_KIND == 0);
113
  return kind <= HOLEY_DOUBLE_ELEMENTS;
114 115
}

116
inline bool IsTransitionElementsKind(ElementsKind kind) {
117
  return IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind) ||
118 119
         kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
         kind == FAST_STRING_WRAPPER_ELEMENTS;
120 121
}

122
inline bool IsDoubleElementsKind(ElementsKind kind) {
123
  return kind == PACKED_DOUBLE_ELEMENTS || kind == HOLEY_DOUBLE_ELEMENTS;
124 125 126
}


127 128 129 130 131
inline bool IsFixedFloatElementsKind(ElementsKind kind) {
  return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
}


132
inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
133
  return IsDoubleElementsKind(kind) || IsFixedFloatElementsKind(kind);
134 135
}

136
inline bool IsSmiOrObjectElementsKind(ElementsKind kind) {
137 138
  return kind == PACKED_SMI_ELEMENTS || kind == HOLEY_SMI_ELEMENTS ||
         kind == PACKED_ELEMENTS || kind == HOLEY_ELEMENTS;
139 140
}

141
inline bool IsSmiElementsKind(ElementsKind kind) {
142
  return kind == PACKED_SMI_ELEMENTS || kind == HOLEY_SMI_ELEMENTS;
143 144
}

145
inline bool IsFastNumberElementsKind(ElementsKind kind) {
146
  return IsSmiElementsKind(kind) || IsDoubleElementsKind(kind);
147 148
}

149
inline bool IsObjectElementsKind(ElementsKind kind) {
150
  return kind == PACKED_ELEMENTS || kind == HOLEY_ELEMENTS;
151 152
}

153
inline bool IsHoleyElementsKind(ElementsKind kind) {
154 155
  return kind == HOLEY_SMI_ELEMENTS || kind == HOLEY_DOUBLE_ELEMENTS ||
         kind == HOLEY_ELEMENTS;
156 157
}

158
inline bool IsHoleyOrDictionaryElementsKind(ElementsKind kind) {
159
  return IsHoleyElementsKind(kind) || kind == DICTIONARY_ELEMENTS;
160 161 162 163
}


inline bool IsFastPackedElementsKind(ElementsKind kind) {
164 165
  return kind == PACKED_SMI_ELEMENTS || kind == PACKED_DOUBLE_ELEMENTS ||
         kind == PACKED_ELEMENTS;
166 167 168 169
}


inline ElementsKind GetPackedElementsKind(ElementsKind holey_kind) {
170 171
  if (holey_kind == HOLEY_SMI_ELEMENTS) {
    return PACKED_SMI_ELEMENTS;
172
  }
173 174
  if (holey_kind == HOLEY_DOUBLE_ELEMENTS) {
    return PACKED_DOUBLE_ELEMENTS;
175
  }
176 177
  if (holey_kind == HOLEY_ELEMENTS) {
    return PACKED_ELEMENTS;
178 179 180 181 182 183
  }
  return holey_kind;
}


inline ElementsKind GetHoleyElementsKind(ElementsKind packed_kind) {
184 185
  if (packed_kind == PACKED_SMI_ELEMENTS) {
    return HOLEY_SMI_ELEMENTS;
186
  }
187 188
  if (packed_kind == PACKED_DOUBLE_ELEMENTS) {
    return HOLEY_DOUBLE_ELEMENTS;
189
  }
190 191
  if (packed_kind == PACKED_ELEMENTS) {
    return HOLEY_ELEMENTS;
192 193 194 195
  }
  return packed_kind;
}

196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
inline bool UnionElementsKindUptoPackedness(ElementsKind* a_out,
                                            ElementsKind b) {
  // Assert that the union of two ElementKinds can be computed via std::max.
  static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS,
                "ElementsKind union not computable via std::max.");
  static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS,
                "ElementsKind union not computable via std::max.");
  static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS,
                "ElementsKind union not computable via std::max.");
  ElementsKind a = *a_out;
  switch (a) {
    case HOLEY_SMI_ELEMENTS:
    case PACKED_SMI_ELEMENTS:
      if (b == PACKED_SMI_ELEMENTS || b == HOLEY_SMI_ELEMENTS) {
        *a_out = std::max(a, b);
        return true;
      }
      break;
    case PACKED_ELEMENTS:
    case HOLEY_ELEMENTS:
      if (b == PACKED_ELEMENTS || b == HOLEY_ELEMENTS) {
        *a_out = std::max(a, b);
        return true;
      }
      break;
    case PACKED_DOUBLE_ELEMENTS:
    case HOLEY_DOUBLE_ELEMENTS:
      if (b == PACKED_DOUBLE_ELEMENTS || b == HOLEY_DOUBLE_ELEMENTS) {
        *a_out = std::max(a, b);
        return true;
      }
      break;
    default:
      break;
  }
  return false;
}
233

234
bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b);
235

236
inline ElementsKind FastSmiToObjectElementsKind(ElementsKind from_kind) {
237
  DCHECK(IsSmiElementsKind(from_kind));
238
  return (from_kind == PACKED_SMI_ELEMENTS) ? PACKED_ELEMENTS : HOLEY_ELEMENTS;
239 240 241 242 243 244
}


inline bool IsSimpleMapChangeTransition(ElementsKind from_kind,
                                        ElementsKind to_kind) {
  return (GetHoleyElementsKind(from_kind) == to_kind) ||
245
         (IsSmiElementsKind(from_kind) && IsObjectElementsKind(to_kind));
246 247 248 249 250 251 252
}


bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
                                         ElementsKind to_kind);


253 254 255 256 257 258 259 260 261
inline ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind,
                                               ElementsKind to_kind) {
  if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
    return to_kind;
  }
  return from_kind;
}


262 263
inline bool IsTransitionableFastElementsKind(ElementsKind from_kind) {
  return IsFastElementsKind(from_kind) &&
264
         from_kind != TERMINAL_FAST_ELEMENTS_KIND;
265 266 267
}


268 269
}  // namespace internal
}  // namespace v8
270 271

#endif  // V8_ELEMENTS_KIND_H_