blob: f0f155e1eb820805474710c96e4b51c2aa9a3170 [file] [log] [blame]
// 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/objects/elements-kind.h"
#include "src/base/lazy-instance.h"
#include "src/objects/elements.h"
#include "src/objects/objects-inl.h"
#include "src/objects/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 PACKED_FROZEN_ELEMENTS:
case PACKED_SEALED_ELEMENTS:
case HOLEY_SMI_ELEMENTS:
case HOLEY_ELEMENTS:
case HOLEY_FROZEN_ELEMENTS:
case HOLEY_SEALED_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 kTaggedSizeLog2;
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) {
switch (kind) {
case PACKED_SMI_ELEMENTS:
return "PACKED_SMI_ELEMENTS";
case HOLEY_SMI_ELEMENTS:
return "HOLEY_SMI_ELEMENTS";
case PACKED_ELEMENTS:
return "PACKED_ELEMENTS";
case HOLEY_ELEMENTS:
return "HOLEY_ELEMENTS";
case PACKED_DOUBLE_ELEMENTS:
return "PACKED_DOUBLE_ELEMENTS";
case HOLEY_DOUBLE_ELEMENTS:
return "HOLEY_DOUBLE_ELEMENTS";
case PACKED_SEALED_ELEMENTS:
return "PACKED_SEALED_ELEMENTS";
case HOLEY_SEALED_ELEMENTS:
return "HOLEY_SEALED_ELEMENTS";
case PACKED_FROZEN_ELEMENTS:
return "PACKED_FROZEN_ELEMENTS";
case HOLEY_FROZEN_ELEMENTS:
return "HOLEY_FROZEN_ELEMENTS";
case DICTIONARY_ELEMENTS:
return "DICTIONARY_ELEMENTS";
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
return "FAST_SLOPPY_ARGUMENTS_ELEMENTS";
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
return "SLOW_SLOPPY_ARGUMENTS_ELEMENTS";
case FAST_STRING_WRAPPER_ELEMENTS:
return "FAST_STRING_WRAPPER_ELEMENTS";
case SLOW_STRING_WRAPPER_ELEMENTS:
return "SLOW_STRING_WRAPPER_ELEMENTS";
#define PRINT_NAME(Type, type, TYPE, _) \
case TYPE##_ELEMENTS: \
return #TYPE "ELEMENTS";
TYPED_ARRAYS(PRINT_NAME);
#undef PRINT_NAME
case NO_ELEMENTS:
return "NO_ELEMENTS";
}
}
ElementsKind kFastElementsKindSequence[kFastElementsKindCount] = {
PACKED_SMI_ELEMENTS, // 0
HOLEY_SMI_ELEMENTS, // 1
PACKED_DOUBLE_ELEMENTS, // 2
HOLEY_DOUBLE_ELEMENTS, // 3
PACKED_ELEMENTS, // 4
HOLEY_ELEMENTS // 5
};
STATIC_ASSERT(PACKED_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
// 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);
ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
DCHECK(sequence_number >= 0 && sequence_number < kFastElementsKindCount);
return kFastElementsKindSequence[sequence_number];
}
int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
for (int i = 0; i < kFastElementsKindCount; ++i) {
if (kFastElementsKindSequence[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