elements-kind.cc 4.77 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
#include "src/elements-kind.h"
6

7
#include "src/api.h"
8
#include "src/base/lazy-instance.h"
9 10
#include "src/elements.h"
#include "src/objects.h"
11 12 13 14 15

namespace v8 {
namespace internal {


16 17
int ElementsKindToShiftSize(ElementsKind elements_kind) {
  switch (elements_kind) {
18 19 20
    case UINT8_ELEMENTS:
    case INT8_ELEMENTS:
    case UINT8_CLAMPED_ELEMENTS:
21
      return 0;
22 23
    case UINT16_ELEMENTS:
    case INT16_ELEMENTS:
24
      return 1;
25 26 27
    case UINT32_ELEMENTS:
    case INT32_ELEMENTS:
    case FLOAT32_ELEMENTS:
28 29 30
      return 2;
    case FAST_DOUBLE_ELEMENTS:
    case FAST_HOLEY_DOUBLE_ELEMENTS:
31
    case FLOAT64_ELEMENTS:
32 33 34 35 36 37
      return 3;
    case FAST_SMI_ELEMENTS:
    case FAST_ELEMENTS:
    case FAST_HOLEY_SMI_ELEMENTS:
    case FAST_HOLEY_ELEMENTS:
    case DICTIONARY_ELEMENTS:
38 39
    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
40 41
    case FAST_STRING_WRAPPER_ELEMENTS:
    case SLOW_STRING_WRAPPER_ELEMENTS:
42
      return kPointerSizeLog2;
43 44 45
    case NO_ELEMENTS:
      UNREACHABLE();
      return 0;
46 47 48 49 50 51
  }
  UNREACHABLE();
  return 0;
}


52
int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
53
  STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
54

55
  if (IsFixedTypedArrayElementsKind(elements_kind)) {
56 57 58 59
    return 0;
  } else {
    return FixedArray::kHeaderSize - kHeapObjectTag;
  }
60 61 62
}


63
const char* ElementsKindToString(ElementsKind kind) {
64
  ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
65 66 67 68
  return accessor->name();
}


69 70 71 72 73 74 75 76 77 78 79 80 81
struct InitializeFastElementsKindSequence {
  static void Construct(
      ElementsKind** fast_elements_kind_sequence_ptr) {
    ElementsKind* fast_elements_kind_sequence =
        new ElementsKind[kFastElementsKindCount];
    *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
    STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
    fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS;
    fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS;
    fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS;
    fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS;
    fast_elements_kind_sequence[4] = FAST_ELEMENTS;
    fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS;
82 83 84 85 86 87 88 89

    // Verify that kFastElementsKindPackedToHoley is correct.
    STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
                  FAST_HOLEY_SMI_ELEMENTS);
    STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
                  FAST_HOLEY_DOUBLE_ELEMENTS);
    STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley ==
                  FAST_HOLEY_ELEMENTS);
90 91 92 93
  }
};


94 95
static base::LazyInstance<ElementsKind*,
                          InitializeFastElementsKindSequence>::type
96 97 98 99
    fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;


ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
100
  DCHECK(sequence_number >= 0 &&
101 102 103 104
         sequence_number < kFastElementsKindCount);
  return fast_elements_kind_sequence.Get()[sequence_number];
}

105

106 107 108 109 110 111 112 113 114 115 116
int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
  for (int i = 0; i < kFastElementsKindCount; ++i) {
    if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
      return i;
    }
  }
  UNREACHABLE();
  return 0;
}


117
ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
118 119
  int index = GetSequenceIndexFromFastElementsKind(kind);
  return GetFastElementsKindFromSequenceIndex(index + 1);
120 121 122
}


123 124 125 126 127
static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
  return IsFastElementsKind(elements_kind) ||
      elements_kind == DICTIONARY_ELEMENTS;
}

128 129
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
                                         ElementsKind to_kind) {
130 131 132
  if (IsFixedTypedArrayElementsKind(from_kind) ||
      IsFixedTypedArrayElementsKind(to_kind)) {
    return false;
133
  }
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
  if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) {
    switch (from_kind) {
      case FAST_SMI_ELEMENTS:
        return to_kind != FAST_SMI_ELEMENTS;
      case FAST_HOLEY_SMI_ELEMENTS:
        return to_kind != FAST_SMI_ELEMENTS &&
            to_kind != FAST_HOLEY_SMI_ELEMENTS;
      case FAST_DOUBLE_ELEMENTS:
        return to_kind != FAST_SMI_ELEMENTS &&
            to_kind != FAST_HOLEY_SMI_ELEMENTS &&
            to_kind != FAST_DOUBLE_ELEMENTS;
      case FAST_HOLEY_DOUBLE_ELEMENTS:
        return to_kind == FAST_ELEMENTS ||
            to_kind == FAST_HOLEY_ELEMENTS;
      case FAST_ELEMENTS:
        return to_kind == FAST_HOLEY_ELEMENTS;
      case FAST_HOLEY_ELEMENTS:
        return false;
      default:
        return false;
    }
155
  }
156
  return false;
157 158 159
}


160 161
}  // namespace internal
}  // namespace v8