// 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.h" namespace v8 { namespace internal { int ElementsKindToShiftSize(ElementsKind elements_kind) { switch (elements_kind) { case EXTERNAL_INT8_ELEMENTS: case EXTERNAL_UINT8_CLAMPED_ELEMENTS: case EXTERNAL_UINT8_ELEMENTS: case UINT8_ELEMENTS: case INT8_ELEMENTS: case UINT8_CLAMPED_ELEMENTS: return 0; case EXTERNAL_INT16_ELEMENTS: case EXTERNAL_UINT16_ELEMENTS: case UINT16_ELEMENTS: case INT16_ELEMENTS: return 1; case EXTERNAL_INT32_ELEMENTS: case EXTERNAL_UINT32_ELEMENTS: case EXTERNAL_FLOAT32_ELEMENTS: case UINT32_ELEMENTS: case INT32_ELEMENTS: case FLOAT32_ELEMENTS: return 2; case EXTERNAL_FLOAT64_ELEMENTS: case FAST_DOUBLE_ELEMENTS: case FAST_HOLEY_DOUBLE_ELEMENTS: case FLOAT64_ELEMENTS: return 3; case FAST_SMI_ELEMENTS: case FAST_ELEMENTS: case FAST_HOLEY_SMI_ELEMENTS: case FAST_HOLEY_ELEMENTS: case DICTIONARY_ELEMENTS: case SLOPPY_ARGUMENTS_ELEMENTS: return kPointerSizeLog2; } UNREACHABLE(); return 0; } int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) { STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); return IsExternalArrayElementsKind(elements_kind) ? 0 : (FixedArray::kHeaderSize - kHeapObjectTag); } const char* ElementsKindToString(ElementsKind kind) { ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); return accessor->name(); } 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; // 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); } }; static base::LazyInstance::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(); return 0; } ElementsKind GetNextTransitionElementsKind(ElementsKind kind) { switch (kind) { #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS; TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE) #undef FIXED_TYPED_ARRAY_CASE default: { int index = GetSequenceIndexFromFastElementsKind(kind); return GetFastElementsKindFromSequenceIndex(index + 1); } } } ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind, bool allow_only_packed) { DCHECK(IsFastElementsKind(elements_kind)); DCHECK(elements_kind != TERMINAL_FAST_ELEMENTS_KIND); while (true) { elements_kind = GetNextTransitionElementsKind(elements_kind); if (!IsFastHoleyElementsKind(elements_kind) || !allow_only_packed) { return elements_kind; } } UNREACHABLE(); return TERMINAL_FAST_ELEMENTS_KIND; } static bool IsTypedArrayElementsKind(ElementsKind elements_kind) { return IsFixedTypedArrayElementsKind(elements_kind) || IsExternalArrayElementsKind(elements_kind); } static inline bool IsFastTransitionTarget(ElementsKind elements_kind) { return IsFastElementsKind(elements_kind) || elements_kind == DICTIONARY_ELEMENTS; } bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind) { if (IsTypedArrayElementsKind(from_kind) || IsTypedArrayElementsKind(to_kind)) { switch (from_kind) { #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ case TYPE##_ELEMENTS: \ return to_kind == EXTERNAL_##TYPE##_ELEMENTS; TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE); #undef FIXED_TYPED_ARRAY_CASE default: return false; } } 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; } } return false; } } } // namespace v8::internal