elements-kind.h 8.17 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 52
  UINT8_ELEMENTS,
  INT8_ELEMENTS,
  UINT16_ELEMENTS,
  INT16_ELEMENTS,
  UINT32_ELEMENTS,
  INT32_ELEMENTS,
  FLOAT32_ELEMENTS,
  FLOAT64_ELEMENTS,
  UINT8_CLAMPED_ELEMENTS,

53 54 55 56
  // Sentinel ElementsKind for objects with no elements.
  NO_ELEMENTS,

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

const int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
67 68
const int kFastElementsKindCount =
    LAST_FAST_ELEMENTS_KIND - FIRST_FAST_ELEMENTS_KIND + 1;
69

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

74
int ElementsKindToShiftSize(ElementsKind elements_kind);
75
int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind);
76
const char* ElementsKindToString(ElementsKind kind);
77

78
inline ElementsKind GetInitialFastElementsKind() { return PACKED_SMI_ELEMENTS; }
79

80
ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number);
81 82
int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind);

83
ElementsKind GetNextTransitionElementsKind(ElementsKind elements_kind);
84

85 86 87 88
inline bool IsDictionaryElementsKind(ElementsKind kind) {
  return kind == DICTIONARY_ELEMENTS;
}

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

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

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

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

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

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

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


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


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

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

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

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

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

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

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


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


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


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

194 195 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
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;
}
231

232
bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b);
233

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


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


bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
                                         ElementsKind to_kind);


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


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


266 267
}  // namespace internal
}  // namespace v8
268 269

#endif  // V8_ELEMENTS_KIND_H_