// 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/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:
    case BIGINT64_ELEMENTS:
    case BIGUINT64_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 ElementsKindToByteSize(ElementsKind elements_kind) {
  return 1 << ElementsKindToShiftSize(elements_kind);
}

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 (!IsFastElementsKind(from_kind)) return false;
  if (!IsFastTransitionTarget(to_kind)) return false;
  DCHECK(!IsFixedTypedArrayElementsKind(from_kind));
  DCHECK(!IsFixedTypedArrayElementsKind(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;
  }
}

bool UnionElementsKindUptoSize(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(HOLEY_SMI_ELEMENTS < PACKED_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 PACKED_SMI_ELEMENTS:
      switch (b) {
        case PACKED_SMI_ELEMENTS:
        case HOLEY_SMI_ELEMENTS:
        case PACKED_ELEMENTS:
        case HOLEY_ELEMENTS:
          *a_out = b;
          return true;
        default:
          return false;
      }
    case HOLEY_SMI_ELEMENTS:
      switch (b) {
        case PACKED_SMI_ELEMENTS:
        case HOLEY_SMI_ELEMENTS:
          *a_out = HOLEY_SMI_ELEMENTS;
          return true;
        case PACKED_ELEMENTS:
        case HOLEY_ELEMENTS:
          *a_out = HOLEY_ELEMENTS;
          return true;
        default:
          return false;
      }
    case PACKED_ELEMENTS:
      switch (b) {
        case PACKED_SMI_ELEMENTS:
        case PACKED_ELEMENTS:
          *a_out = PACKED_ELEMENTS;
          return true;
        case HOLEY_SMI_ELEMENTS:
        case HOLEY_ELEMENTS:
          *a_out = HOLEY_ELEMENTS;
          return true;
        default:
          return false;
      }
    case HOLEY_ELEMENTS:
      switch (b) {
        case PACKED_SMI_ELEMENTS:
        case HOLEY_SMI_ELEMENTS:
        case PACKED_ELEMENTS:
        case HOLEY_ELEMENTS:
          *a_out = HOLEY_ELEMENTS;
          return true;
        default:
          return false;
      }
      break;
    case PACKED_DOUBLE_ELEMENTS:
      switch (b) {
        case PACKED_DOUBLE_ELEMENTS:
        case HOLEY_DOUBLE_ELEMENTS:
          *a_out = b;
          return true;
        default:
          return false;
      }
    case HOLEY_DOUBLE_ELEMENTS:
      switch (b) {
        case PACKED_DOUBLE_ELEMENTS:
        case HOLEY_DOUBLE_ELEMENTS:
          *a_out = HOLEY_DOUBLE_ELEMENTS;
          return true;
        default:
          return false;
      }

      break;
    default:
      break;
  }
  return false;
}

}  // namespace internal
}  // namespace v8
