// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/elements-kind.h"

#include "src/api.h"
#include "src/base/lazy-instance.h"
#include "src/elements.h"
#include "src/objects-inl.h"
#include "src/objects.h"

namespace v8 {
namespace internal {


int ElementsKindToShiftSize(ElementsKind elements_kind) {
  switch (elements_kind) {
    case UINT8_ELEMENTS:
    case INT8_ELEMENTS:
    case UINT8_CLAMPED_ELEMENTS:
      return 0;
    case UINT16_ELEMENTS:
    case INT16_ELEMENTS:
      return 1;
    case UINT32_ELEMENTS:
    case INT32_ELEMENTS:
    case FLOAT32_ELEMENTS:
      return 2;
    case PACKED_DOUBLE_ELEMENTS:
    case HOLEY_DOUBLE_ELEMENTS:
    case FLOAT64_ELEMENTS:
      return 3;
    case PACKED_SMI_ELEMENTS:
    case PACKED_ELEMENTS:
    case HOLEY_SMI_ELEMENTS:
    case HOLEY_ELEMENTS:
    case DICTIONARY_ELEMENTS:
    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
    case FAST_STRING_WRAPPER_ELEMENTS:
    case SLOW_STRING_WRAPPER_ELEMENTS:
      return kPointerSizeLog2;
    case NO_ELEMENTS:
      UNREACHABLE();
  }
  UNREACHABLE();
}


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

  if (IsFixedTypedArrayElementsKind(elements_kind)) {
    return 0;
  } else {
    return FixedArray::kHeaderSize - kHeapObjectTag;
  }
}


const char* ElementsKindToString(ElementsKind kind) {
  ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
  return accessor->name();
}


struct InitializeFastElementsKindSequence {
  static void Construct(void* fast_elements_kind_sequence_ptr_arg) {
    auto fast_elements_kind_sequence_ptr =
        reinterpret_cast<ElementsKind**>(fast_elements_kind_sequence_ptr_arg);
    ElementsKind* fast_elements_kind_sequence =
        new ElementsKind[kFastElementsKindCount];
    *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
    STATIC_ASSERT(PACKED_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
    fast_elements_kind_sequence[0] = PACKED_SMI_ELEMENTS;
    fast_elements_kind_sequence[1] = HOLEY_SMI_ELEMENTS;
    fast_elements_kind_sequence[2] = PACKED_DOUBLE_ELEMENTS;
    fast_elements_kind_sequence[3] = HOLEY_DOUBLE_ELEMENTS;
    fast_elements_kind_sequence[4] = PACKED_ELEMENTS;
    fast_elements_kind_sequence[5] = HOLEY_ELEMENTS;

    // Verify that kFastElementsKindPackedToHoley is correct.
    STATIC_ASSERT(PACKED_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
                  HOLEY_SMI_ELEMENTS);
    STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
                  HOLEY_DOUBLE_ELEMENTS);
    STATIC_ASSERT(PACKED_ELEMENTS + kFastElementsKindPackedToHoley ==
                  HOLEY_ELEMENTS);
  }
};


static base::LazyInstance<ElementsKind*,
                          InitializeFastElementsKindSequence>::type
    fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;


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


int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
  for (int i = 0; i < kFastElementsKindCount; ++i) {
    if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
      return i;
    }
  }
  UNREACHABLE();
}


ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
  int index = GetSequenceIndexFromFastElementsKind(kind);
  return GetFastElementsKindFromSequenceIndex(index + 1);
}


static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
  return IsFastElementsKind(elements_kind) ||
      elements_kind == DICTIONARY_ELEMENTS;
}

bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
                                         ElementsKind to_kind) {
  if (IsFixedTypedArrayElementsKind(from_kind) ||
      IsFixedTypedArrayElementsKind(to_kind)) {
    return false;
  }
  if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) {
    switch (from_kind) {
      case PACKED_SMI_ELEMENTS:
        return to_kind != PACKED_SMI_ELEMENTS;
      case HOLEY_SMI_ELEMENTS:
        return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS;
      case PACKED_DOUBLE_ELEMENTS:
        return to_kind != PACKED_SMI_ELEMENTS &&
               to_kind != HOLEY_SMI_ELEMENTS &&
               to_kind != PACKED_DOUBLE_ELEMENTS;
      case HOLEY_DOUBLE_ELEMENTS:
        return to_kind == PACKED_ELEMENTS || to_kind == HOLEY_ELEMENTS;
      case PACKED_ELEMENTS:
        return to_kind == HOLEY_ELEMENTS;
      case HOLEY_ELEMENTS:
        return false;
      default:
        return false;
    }
  }
  return false;
}


}  // namespace internal
}  // namespace v8
